Simple injector cannot override existing registration

I am currently using Simple Injector for the first time. In my .NET project, I run the test and bullying data returned from the web service and register it in the container like this

_container.Register<IWebServiceOrder>(() => mock.Object, Lifestyle.Transient); 

It works great. But in my tests, I want to check the behavior of the system in the second call to the web service, which will contain the updated data, so the layout should be updated.

By default, Simple Injector does not allow you to redefine existing registrations, but the official website claims that this can be changed, as shown below.

https://simpleinjector.readthedocs.org/en/latest/howto.html#override-existing-registrations

 container.Options.AllowOverridingRegistrations = true; 

Unfortunately, I still get an error message when I try to register an object a second time even with the code above.

The container cannot be changed after the first call to GetInstance, GetAllInstances and Verify

Any ideas on why this is happening?

+5
source share
1 answer

Replacing an existing registration after you have already worked with the container is unlikely to ever have the behavior you expect (and this is true for all DI libraries) and that the reason the Simple Injector container is locked. This is described in more detail here (as @qujck already pointed out).

First of all, if you are writing unit tests, you should not use the container at all. Your unit tests must create the class itself or you extract this logic for a convenient factory method, for example:

 private static MailNotifier CreateMailNotifier( IDeposit deposit = null, ISendMail mailSender = null, ILog logger = null) { return new MailNotifier( deposit ?? Substitute.For<IDeposit>(), mailSender ?? Substitute.For<ISendMail>(), logger ?? Substitute.For<ILog>()); } 

This factory method is a variant of the Test Data Builder template.

Using optional parameters, it allows the unit test to specify only the fake implementation that is required during testing:

 public void Notify_WithValidUser_LogsAMessage() { // Arrange var user = new User(); var logger = new FakeLogger(); MailNotifier sut = CreateMailNotifier(logger: logger); // Act sut.Notify(user); // Assert Assert.AreEqual(expected: 1, actual: logger.LoggedMessages.Count); } 

If you use the container, because creating a class under control manually is too cumbersome, this indicates a problem in the tested class (most likely, this is a violation of the principle of uniform responsibility). Prevent the use of tools to solve problems in your design; your code is talking to you.

However, for integration tests it is much more convenient to use a container, but in this case you just need to create a new container for each integration test. This way you can add or replace IWebServiceOrder without any problems.

+9
source

Source: https://habr.com/ru/post/1205171/


All Articles