You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NSubstituteBinder.CreateInstance being abstract dose allow for some kind of caching wrapper to be implemented independently.
It can be hard to explain in an abstract way but this article shows why it can be useful to have this functionality, using AutoFixture and Moq. The idea being that by injecting the same instance into the test it cuts down on lines of copy and paste code. So the start of the test doesn't have the same boiler plate of setting up the mock classes. Also with the current setup it may not be possible to alter the mock after the class has been constructed, if the mock is private/protected.
I find it hard to make up an example but hopefully, the code bellow will illustrate how this can be useful. Especially if the interface you need to mock is several layers of instantiation deep A -makes-> B -has interface-> IC, that you are trying to test.
publicclassMockClass(IRepositoryrepository){publicIRepositoryRepository=>repository;//only exposed for testspublicasyncTask<Model>GetModelWithId(Guidid){returnawaitrepository.Get(id);}}publicinterfaceIRepository{Task<Model>Get(Guidid);}publicrecordModel(GuidId);publicclassTestExample{// This would be the normal way of setting up test using NSubstitute[Fact]publicasyncTaskGetModelWithId_ShouldCallRepository_WithCorrectId(){// arrange// lots of lines to just make the sub and configure it, this gets annoying when you have 3+ dependencies and need to alter for every testvarrepository=Substitute.For<IRepository>();varexpectedModel=newModel(Guid.NewGuid());varid=Guid.NewGuid();repository.Get(id).Returns(expectedModel);// then make the test classvartestClass=newMockClass(repository);// actvarresult=awaittestClass.GetModelWithId(id);// assertresult.Should().Be(expectedModel);awaitrepository.Received().Get(id);}[Fact]// With the current AutoBogus this isn't possible to test, the Repository has to be public, so the test can access it.// In most cases I don't think this would be the correct design, since it will be altered just to test the functinality.publicasyncTaskGetModelWithId_ShouldCallRepository_WithCorrectId_UsingAutoFaker(){// arrangevartestClass=newAutoFaker().Generate<MockClass>();// if the repository was public could so thisvartestModel=newModel(Guid.NewGuid());testClass.Repository.Get(testModel.Id).Returns(testModel);// actvarresult=awaittestClass.GetModelWithId(testModel.Id);// assertresult.Should().Be(testModel);awaittestClass.Repository.Received().Get(testModel.Id);}// If the interface can be frozen then this becomes something like// With the current AutoBogus this isn't possible to test[Fact]publicasyncTaskGetModelWithId_ShouldCallRepository_WithCorrectId_UsingAutoFakerWithAFrozen(){// arrangevarfaker=newAutoFaker();varrepository=faker.Generate<IRepository>();// with an attribute like - frozen: truevartestModel=faker.Generate<Model>();repository.Get(testModel.Id).Returns(testModel);vartestClass=faker.Generate<MockClass>();// actvarresult=awaittestClass.GetModelWithId(testModel.Id);// assertresult.Should().Be(testModel);awaitrepository.Received().Get(testModel.Id);}// This becomes most powerful when you combine it with an attribute to autopopulate the values[Fact]publicasyncTaskGetModelWithId_ShouldCallRepository_WithCorrectId([Frozen]IRepositoryrepository,ModeltestModel,MockClasstestClass){// arrangerepository.Get(testModel.Id).Returns(testModel);// actvarresult=awaittestClass.GetModelWithId(testModel.Id);// assertresult.Should().Be(testModel);awaitrepository.Received().Get(testModel.Id);}}
Also want to say, there is no expectation for you to take the library this way. These are only suggestions from how I want to use testing libraries. Ultimately I can just fork this and Bogus to make the modifications I want to see. I am happy to help extend this library though if you see the value of this approach.
The text was updated successfully, but these errors were encountered:
This is a continuation of the discutions in AutoBogus PR#263.
NSubstituteBinder.CreateInstance being abstract dose allow for some kind of caching wrapper to be implemented independently.
It can be hard to explain in an abstract way but this article shows why it can be useful to have this functionality, using AutoFixture and Moq. The idea being that by injecting the same instance into the test it cuts down on lines of copy and paste code. So the start of the test doesn't have the same boiler plate of setting up the mock classes. Also with the current setup it may not be possible to alter the mock after the class has been constructed, if the mock is private/protected.
I find it hard to make up an example but hopefully, the code bellow will illustrate how this can be useful. Especially if the interface you need to mock is several layers of instantiation deep A -makes-> B -has interface-> IC, that you are trying to test.
Also want to say, there is no expectation for you to take the library this way. These are only suggestions from how I want to use testing libraries. Ultimately I can just fork this and Bogus to make the modifications I want to see. I am happy to help extend this library though if you see the value of this approach.
The text was updated successfully, but these errors were encountered: