I have a sut with the dependency:
public interface IDep
{
void Click(int c);
}
public class Sut
{
public Sut(IDep dep)
{
dep.Click(10);
}
}
in my test I want to check that Click was called, but it does not work without being frozen.
var fixture = new Fixture().Customize(
new AutoNSubstituteCustomization { ConfigureMembers = true }
);
//fixture.Freeze<IDep>(); // uncommenting this line make it working
fixture.Create<Sut>();
fixture.Freeze<IDep>()
.Received(1)
.Click(Arg.Any<int>);
in my test I want to check that Click was called, but it does not work without being frozen.
That is by design. That freeze line is necessary to capture a single mocked dependency.
In this case the dependency injected into the SUT and the one you try to get after with the freeze will be different instances. Which is why your particular test case fails.
I would suggest keeping the first line and pass the returned value to a variable. You can then perform your assertion on the variable after exercising the SUT in this particular case.
For example
var fixture = new Fixture().Customize(
new AutoNSubstituteCustomization { ConfigureMembers = true }
);
//Arrange
IDep dependency = fixture.Freeze<IDep>();
//...any configuration needed on the mock can be done here
//Act
Sut sut = fixture.Create<Sut>(); //frozen dependency will be injected into sut.
//Assert
dependency.Received(1).Click(Arg.Any<int>);
I suggest reviewing the Quick Start to get a better understanding of what is the purpose of the Freeze functionality
Luckily we can tell our fixture to “freeze” a particular type. This means that every time we request an instance of a frozen type, we will get the same instance. You can think of it as registering a singleton instance in an IoC container.
Related
I have a class which inherited from IWindsorInstaller. I use this class to install/register the dependencies. Now I want to write tests for this class.
I register in the container a dependency with parameter. Like this:
container.Register(Component.For<IXService>().ImplementedBy<XService>().DependsOn(Dependency.OnComponent("operationY", "OperationY")).LifeStyle.Singleton);
Now in my Unit-Test, I want to verify if it is registered correctly. Something like this:
_containerMock.Verify(f=>f.Register(It.IsAny<ComponentRegistration<IXService>>().ImplementedBy<XService>().DependsOn(Dependency.OnComponent("operationY", "OperationY")).LifestyleSingleton()),Times.AtLeastOnce);
I don't have any idea, what should I do?
Thanks in advance, Mo.
Your unit test is not there to prove that the container has a registration for a given service.
It's to prove that the container can resolve that service (the fact that a registration exists is an implementation detail).
So, in your unit test, just attempt to resolve your service and verify it's what you are looking for, e.g:
public void UnitTest_Prove_That_Service_Can_Be_Created()
{
var sut = new SystemUnderTest();
var container = sut.GetContainer();
var service = container.Resolve<IXService>();
// Prove the IXService resolves to an XService - i.e. the registration
// has the correct mapping.
Assert.Type<XService>(service);
}
Additionally, you might want to prove it's a singleton:
public void UnitTest_Prove_That_Service_Is_A_Singleton()
{
var sut = new SystemUnderTest();
var container = sut.GetContainer();
var service1 = container.Resolve<IXService>();
var service2 = container.Resolve<IXService>();
// Prove you got the same service back each time - i.e. it's a singleton
Assert.Equals(service1, service2);
}
EDIT
The fact that the SUT is an IWindsorInstaller doesn't really change my answer. Just tweak the unit test slightly:
public void UnitTest_Prove_That_Service_Can_Be_Created()
{
var container = new WindsorContainer();
container.Install(new SystemUnderTest());
var service = container.Resolve<IXService>();
// Prove the IXService resolves to an XService - i.e. the registration
// has the correct mapping.
Assert.Type<XService>(service);
}
I have some problems testing a singleton. When I run this code, I get an error in TestGetLogicalDevices(). CallTo() failed because service is no fake object. When I try to create a fake object (commented code), it gives an error because RestService is a singleton with private constructor. How can I create a fake object of this singleton?
private RestService service;
[TestInitialize]
public void Init()
{
//service = A.Fake<RestService>();
service = RestService.Instance;
service.CreateClient("test", "test");
}
[TestMethod]
public async Task TestGetLogicalDevices()
{
var logicalDevices = (List<LogicalDevice>)A.CollectionOfFake<LogicalDevice>(10);
A.CallTo(() => service.GetLogicalDevices()).Returns(Task.FromResult(logicalDevices));
List<LogicalDevice> collectedData = await service.GetLogicalDevices();
Assert.AreEqual(2, collectedData.Count);
}
public async Task<List<LogicalDevice>> GetLogicalDevices()
{
var response = await client.GetAsync(apiBaseUrl + "/logical-devices");
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var logicalDevices = JsonConvert.DeserializeObject<List<LogicalDevice>>(json);
var sortedList = logicalDevices.OrderBy(logicalDevice => logicalDevice.Name).ToList();
return sortedList;
}
else
{
return null;
}
}
Update
I added the code of my method I want to test. Maybe someone has suggestions for better tests?
Note: I'm not sure I understand what you're trying to do. What are you trying to test exactly? In your test, you configure service.GetLogicalDevices() to return something, then you call service.GetLogicalDevices() and assert what it returns (which, unless FakeItEasy is broken, should be what you configured it to return). So, you're not actually testing the service... you're testing the mocking framework! Mocking frameworks like FakeItEasy are useful to mock the dependencies of the system under test (SUT), not the SUT itself. In your case, if the SUT is RestService, you need to mock the dependencies of RestService, not RestService itself. For instance, you could inject an HttpClient with a HttpMessageHandler that you control (see here for more details).
Now, to answer your actual question (assuming it's really RestService that you want to fake):
When I run this code, I get an error in TestGetLogicalDevices(). CallTo() failed because service is no fake object.
A.CallTo only works on fakes; FakeItEasy can't control the behavior of objects it didn't create.
When I try to create a fake object (commented code), it gives an error because RestService is a singleton with private constructor
RestService is a class, and FakeItEasy can create a fake for a class, but it does it by inheriting the class, so it needs an accessible constructor. Also, keep in mind that only virtual methods can be configured. GetLogicalDevices is not virtual, so the fake can't override its behavior.
You have two main options for faking RestService:
make the constructor protected rather than private, and make the methods virtual so that they can be overriden
create an IRestService interface that represents the "public contract" of the RestService class, and fake that interface instead of the class.
I'm trying to figure out why our integration tests are not independent.
The essential part of each test is:
var builder = new ContainerBuilder();
// IoC registrations, typically SingleInstance lifetimes or RegisterInstance
var browser = new Browser(new CustomBootstrapper(builder));
// browser.Post...
// Assertions
Each test uses fresh ContainerBuilder and Browser instances.
One of our tests passes when run independently, but fails if run along with another similar test. This happens in two different test runners (TestDriven.Net and JetBrains).
Instrumenting, I can see by checking HashCodes that an object used by the first test and injected by the IoC container shows up in the second test (and doesn't match the object created there). Methods are called on the wrong object, so the test fails.
The code doesn't use static members.
Am I misunderstanding something about the way Nancy, Nancy.Testing, or OWIN works? How can these tests influence each other?
Per request, more details:
[Test]
public void Test1()
{
var organizationCache = new OrganizationCache();
// Logs Creating OrganizationCache with HashCode:43641814 (varies by run)
organizationCache.AddOrganization(organization);
ContainerBuilder builder = AutofacTestContainerBuilderFactory.CreateTestContainerBuilder();
builder.RegisterInstance(organizationCache);
var browser = new Browser(new CustomBootstrapper(builder));
BrowserResponse browserResponse = browser.Post(
"/api/...",
with => with.JsonBody(model));
browserResponse.StatusCode.ShouldBe(HttpStatusCode.OK);
}
In separate TestFixture class, with no setup/teardown on either:
[Test]
public void Test2()
{
var organizationCache = new OrganizationCache();
// Logs Creating OrganizationCache with HashCode:5337202 (varies by run)
organizationCache.AddOrganization(organization);
ContainerBuilder builder = AutofacTestContainerBuilderFactory.CreateTestContainerBuilder();
builder.RegisterInstance(organizationCache);
var browser = new Browser(new CustomBootstrapper(builder));
TestHelpers.Authenticate(browser); // log in (does a browser.Post)
BrowserResponse browserResponse = browser.Post(
"/api/...",
with => with.JsonBody(model));
browserResponse.StatusCode.ShouldBe(HttpStatusCode.Created);
// Passes if run independently, fails if run with other test
// When run with other test, system under test logs both OrganizationCache HashCodes during this test
}
Could CookieBasedSessions somehow be affecting this? (Note: I tried removing CookieBasedSessions.Enable and- separately and together- creating a new Session in the pipeline; this did not affect the issue.)
Disposing of the customBootstrapper after each test made no difference either.
(CustomBootstrapper has no static fields and descends from AutofacNancyBootstrapper. It's too long to post here.)
One of our developers found the issue in our code.
using Nancy.Authentication.Forms;
public class UserMapper : IUserMapper
{
public static IOrganizationService OrganizationService { get; set; }
// ...
}
The implementation of IOrganizationService has an OrganizationCache injected into its constructor.
The static field was the culprit.
New to unit testing. I have a WPF client app hooked into a WCF service via basicHttpbinding. Everything works great. I'm using simple constructor Dependency Injection in my viewModel, passing in an IServiceChannel which I then call me service methods on e.g:
IMyserviceChannel = MyService;
public MyViewModel(IMyServiceChannel myService)
{
this.MyService = myService;
}
Private void GetPerson()
{
var selectedPerson = MyService.GetSelectedPerson();
}
I have then added an MS Test project in the client app and I'm trying to use Moq to mock my service:
[TestMethod]
public void GetArticleBody_Test_Valid()
{
// Create channel mock
Mock<IIsesServiceChannel> channelMock = new Mock<IIsesServiceChannel>(MockBehavior.Strict);
// setup the mock to expect the Reverse method to be called
channelMock.Setup(c => c.GetArticleBody(1010000008)).Returns("110,956 bo/d, 1.42 Bcfg/d and 4,900 bc/d. ");
// create string helper and invoke the Reverse method
ArticleDataGridViewModel articleDataGridViewModel = new ArticleDataGridViewModel(channelMock.Object);
string result = channelMock.GetArticleBody(1010000008);
//Assert.AreEqual("cba", result);
//verify that the method was called on the mock
channelMock.Verify(c => c.GetArticleBody(1010000008), Times.Once());
}
The test is failing with a System.NullReferenceException. Object reference not set to an instance of an object. at the method invocation here:
string result = articleDataGridViewModel.IsesService.GetArticleBody(1010000008);
so I'm wandering whether this is the best way to approach or am I better somehow mocking an isolated part of the viewModel which is applicable to the test?
The NullReferenceException is mybe thrown because you use MockBehavior.Strict. The documentation says:
Causes this mock to always throw an exception for invocations that don't have a corresponding setup.
Maybe the constructor of ArticleDataGridViewModel calls other methods of the service which you haven't set up.
Another issue is, that you are calling the mocked method directly. Instead you should call a method of your view model, which calls this method.
[TestMethod]
public void GetArticleBody_Test_Valid()
{
// Create channel mock
Mock<IIsesServiceChannel> channelMock = new Mock<IIsesServiceChannel>();
// setup the mock to expect the Reverse method to be called
channelMock.Setup(c => c.GetArticleBody(1010000008)).Returns("110,956 bo/d, 1.42 Bcfg/d and 4,900 bc/d. ");
// create string helper and invoke the Reverse method
ArticleDataGridViewModel articleDataGridViewModel = new ArticleDataGridViewModel(channelMock.Object);
string result = articleDataGridViewModel.MethodThatCallsService();
//Assert.AreEqual("cba", result);
//verify that the method was called on the mock
channelMock.Verify(c => c.GetArticleBody(1010000008), Times.Once());
}
Besides that I think there is no problem with your approach. Maybe the view model violates the single responsibility principle and does more than it should, but that's hard to tell on the basis of your code example.
EDIT: Here's a full example of how you could test something like this:
public interface IMyService
{
int GetData();
}
public class MyViewModel
{
private readonly IMyService myService;
public MyViewModel(IMyService myService)
{
if (myService == null)
{
throw new ArgumentNullException("myService");
}
this.myService = myService;
}
public string ShowSomething()
{
return "Just a test " + this.myService.GetData();
}
}
class TestClass
{
[TestMethod]
public void TestMethod()
{
var serviceMock = new Mock<IMyService>();
var objectUnderTest = new MyViewModel(serviceMock.Object);
serviceMock.Setup(x => x.GetData()).Returns(42);
var result = objectUnderTest.ShowSomething();
Assert.AreEqual("Just a test 42", result);
serviceMock.Verify(c => c.GetData(), Times.Once());
}
}
Without access to your viewmodel, there's only so much help that we can provide you.
However, this code:
Mock<IIsesServiceChannel> channelMock = new Mock<IIsesServiceChannel>(MockBehavior.Strict);
...
ArticleDataGridViewModel articleDataGridViewModel = new ArticleDataGridViewModel(channelMock.Object);
...
string result = articleDataGridViewModel.IsesService.GetArticleBody(1010000008);
Does not set up your IsesService. If it is not set up in your constructor, that means the IsesService is a null reference. You can't call a method on a null object.
Consider mocking out at a higher level of abstraction then the tight coupling you have with the tool your using.
Perhaps your view-model should rely on services and not a detail of the tool that your using (i.e. IIsesServiceChannel).
Here's an example:
Construct testable business layer logic
I am trying to setup tests for my new projects and come across some difficulties.
I am using NUnit and Rhino Mocks.
The Code that I am trying to test is this,
public DocumentDto SaveDocument(DocumentDto documentDto)
{
Document document = null;
using (_documentRepository.DbContext.BeginTransaction())
{
try
{
if (documentDto.IsDirty)
{
if (documentDto.Id == 0)
{
document = CreateNewDocument(documentDto);
}
else if (documentDto.Id > 0)
{
document = ChangeExistingDocument(documentDto);
}
document = _documentRepository.SaveOrUpdate(document);
_documentRepository.DbContext.CommitChanges();
}
}
catch
{
_documentRepository.DbContext.RollbackTransaction();
throw;
}
}
return MapperFactory.GetDocumentDto(document);
}
And my testing code is as follows
[Test]
public void SaveDocumentsWithNewDocumentWillReturnTheSame()
{
//Arrange
IDocumentService documentService = new DocumentService(_ducumentMockRepository,
_identityOfSealMockRepository, _customsOfficeOfTransitMockRepository,
_accountMockRepository, _documentGuaranteeMockRepository,
_guaranteeMockRepository, _goodsPositionMockRepository);
var documentDto = new NctsDepartureNoDto();
documentDto.IsDirty = true;
documentDto.Id = 0;
//Act
var retDocumentDto = documentService.SaveDocument(documentDto);
//Assert
Assert.AreEqual(documentDto, documentDto);
}
private static IDbContext CreateMockDbContext()
{
var dbContext = MockRepository.GenerateMock<IDbContext>();
// setup expectations for DbContext mock
//dbContextMock.Expect(...)
// bind mock of the DbContext to property of repository.DbContext
_ducumentMockRepository.Expect(mock => mock.DbContext).Return(dbContext).Repeat.Any();
return dbContext;
}
I need to pass in a documentDto with say isDirty set and test if it returns the same object.
So I was thinking to use a Stub instead of a mock.
I need to to find out how to set expectations so I can test the logic on the code.
you need to mock or stub all of the components which you do not want to test. You should, as a rule of thumb only have a maximum of single mock object the rest should be stubs. Mock the things you want to verify interaction with and stub the things which you just want to provide data for your test.
you don't tell us what type your _documentRepository is so its hard to tell exactly what you are testing here, but to test this method the only thing you can do, IMHO, is check that if the IsDirty flag is set is check that the correct methods on the _documentRepository and the Context are called.
To do this I would create a mock _documentRepository and mock DbContext and set expectations that _documentRepository.SaveOrUpdate(document) is called with the document passed in. Actually looking again at the code you need to convert between the dto and the document. Currently this is being done in a method. I would create a interface and a class for this and make that interface a dependency of the class you are testing so that you can create a stub which returns a known document from the documentDto. This class could handle creating a new document or returning an existing one based on the id in the Dto. otherwise you'll have to know what type of document is returned.
something like:
var documentDto = new NctsDepartureNoDto();
documentDto.IsDirty = true;
documentDto.Id = 0;
IDbContext context = MockRepository.GenerateMock<IDbRepository>();
context.Expect(x=>x.BeginTransaction()).Return(MockRepository.GenerateStub<ITransaction>());
context.Expect(x=>x.CommitChanges());
then create a mock for the repository
IDocumentRepository repo = MockRepository.GenerateMock<IDocumentRepository>();
repo.Expect(x=>x.DbContext).Return(context).Repeat().Any();
repo.Expect(x=>x.SaveOrUpdate(Arg<Document>.Is.Any())).Return(MockRepository.GenerateStub<Document>);
This tests that you interact with the repository object correctly when the dirty flag is set. It shouldn't test that the document is saved correctly or that the correct document is returned when SaveOrUpdate is called, as this should be tested in the tests for the repository, not here.
'But wait!' I hear you cry, 'you said at the beginning that there should only be a single mock, and here we have 2!'. That's true, and I think that this shows a fault in your current design.
You should not, I don't think, be exposing the DBContext from your documentRepository. You seem to be doing so in order to use the transactions.
If your repository needs to be aware of the transactions then have methods on the repository that allow the transactions to be controlled (or hide the fact that the transactions exist inside the repository object completely). These methods might just delegate to the internal DbContext but it would then mean that the only mock would need to be the document repository object itself, and not the DbContext