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.
Related
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.
While I understand that when unit testing a method it is very important to mock all it's dependencies, what I still have confusion about is what happens when the method is nested? Do I mock only the dependencies of the parent method or do I mock the dependencies of the child method(s) as well or do I set expectations on the calls to the dependent object and set the exact return values so that I can perform the test that I want?
For instance, in the below example, if we want to unit test the method B, do we only mock IHttpClientFactory & ILogger or do we also set the method's return value to what we are actually expecting because otherwise when the test method executes it goes ahead and tries to execute methodC where it fails because the value of client after the line var client = _clientFactory.CreateClient() executes is null?
using System.Net.Http;
...
public class classA
{
private readonly IHttpClientFactory _clientFactory;
private sting url = "...";
private ILogger _log { get; set; }
...
public classA(ILogger log, IHttpClientFactory clientFactory, ...)
{
_log = log;
_clientFactory = clientFactory;
...
}
public string methodB(string inputB)
{
var varB = methodC(inputB);
...
return ..;
}
public string methodC(string inputC)
{
...
var client = _clientFactory.CreateClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage httpResponseMessage = await client.PostAsync(url, new StringContent(inputC, Encoding.UTF8, "application/json"));
responJsonText = await httpResponseMessage.Content.ReadAsStringAsync();
...
return ..;
}
}
So you have an HTTP client, a high-level method that gets you some structured data and a low-level method that gets you the contents of the response.
These things are more of an art than hard-cut rules, but the rule I prefer most of the time is to write code that can have all of its I/O abstracted and then mock or test-implement the I/O itself. This way the most amount of business logic would be testable.
I/O can be many things - file, network, user input, but even things such as getting a certificate from the cert store or reading registry setting. Any data that originates at runtime from outside the process is I/O, no matter the method.
When you mock functionality, the most common things you're interested in is validating the method's input or emulating its output (or both). So in your mock, you shouldn't be too concerned with the actual implementation since you're not testing your mocked method - you're testing whatever is calling it.
So... about your sample code. If you're trying to test MethodB, you'd need MethodC to have a test implementation - either by mocking the HttpClient it relies on or by making it virtual and having it overridden in test.
Side note: reuse the HttpClient, keep it with the class
I recently took a .Net project over which exposes DAOs from a Microsoft SQL Database via ServiceStack(3.9.71) REST API. Since I am gonna refactor some parts I want to unit test (at least) all servicestack services. For a better understanding I quickly draft how the implementation works.
Each Service contains a property of type DBService which encapsulates all database accesses of all services. Unfortunately this is a concrete class which makes it hard to mock. The DI.Container wrappes ServiceStack's IOC.
public class SomeService : Service
{
public DBService { get { return DI.Container.Resolve<DBService>(); } }
public object Get(SomeDataClass class)
{
var response = DBService.SomeServiceGet();
return response;
}
// other code omitted
}
The DBService looks like this (draft):
public class DBService
{
public IDbConnectionFactory DBFactory { get { return DI.Container.Resolve<IDbConnectionFactory>(); } }
public SomeServiceResponse SomeServiceGet()
{
//DB Access here...
// ...
}
public SomeOtherServiceResponse SomeOtherServiceGet()
{
//...
}
// following about 30 other methods for all the services (POST,GET,PUT etc)
}
I read the detailed response to this question but I was not able to create and initialize a BasicAppHost in ServiceStack 3.9.71 since it immediately threw a System.TypeLoadExceptionMethod 'get_VirtualPathProvider'.
On the other hand I was thinking that I do not actually need a BasicAppHost. I just have to unit test the DBService and then the servicestack services with a somehow mocked DBService. The only problem I have is that DBService is not an interface and that I am actually not sure how to deal (mock) with the SQL database and the IOC.
[UPDATE]
Unfortunately I am still not able to test a service since I can not just new the service in my test. If I do so I get:
System.TypeLoadExceptionCould not load type 'ServiceStack.ServiceHost.IService' from assembly
Here is my test:
[Fact]
public void SomeDataTest()
{
var serviceUnderTest = new SomeService();
var response = serviceUnderTest.Get(new SomeDataClass());
Assert.NotNull(response);
}
I guess the problem is that the services strongly uses alot of properties which are injected via the IOC. How can I mock that? Creating a BasicAppHost and retrieving the service from there also does not work which I already mentioned.
If you are just testing your service class, then you can directly mock any dependencies:
[Fact]
public void SomeDataTest(
{
var serviceUnderTest = new SomeService();
var logger = new Mock<ILogger>(); // Rhino mocks fashion.
serviceUnderTest.Logger = logger.Object;
var response = serviceUnderTest.Get(new SomeDataClass());
Assert.NotNull(response);
}
There's an page in their older docs here about integration testing in case you want to test the AppHost
Edit: there's an example of mocking the service dependencies here.
Given I have a controller class as such:
public class ResourceController : AuthorizedController
{
public virtual string Resource()
{
//do magic
}
public virtual string ResourceParent()
{
var url = Resource();
return url;
}
}
}
With the test harness:
[Subject(typeof (ResourceController))]
public class When_I_want_the_parent_resource : WithSubject<ResourceController>
{
private static readonly string ParentUrl = "/organizations/1";
private static readonly string ResourceUrl = "/organizations/1/contacts/1";
private static string _result;
private Establish context = () =>
{
The<ResourceController>()
.WhenToldTo(x => x.Resource())
.Return(ResourceUrl);
};
private Because of = () => _result = Subject.ResourceParent();
private It should_match_the_expected_parent_url = () =>
_result.ShouldEqual(ParentUrl);
}
This unit test will fail because Subject.ResourceParent() will return null because Machine.Fakes has automocked this method. As a temporary workaround I just removed the virtual keyword from ResourceParent to be able to test my code. I assume there has to be a real solution for me to tell Machine.Fakes to not override ResourceParent()
actually there isn't a "real" solution in Machine.Fakes for this. I would argue that you need to reconsider you're fixture design.
First of all, as Tim already pointed out, you you should't fake any methods on the subject itself. Instead you should fake the dependencies of your controller and use your controller as-is in specifications. The intended usage of the "The" method is to access the dependencies of the subject under specification, but what you try in your spec is to access the subject itself. I think that's where things go wrong. The <ResourceController> and subject are actually separate instances. That's why you configured interaction doesn't happen.
Just some options to fix this in your code:
Introduce a new dependency in your code which you can stub via "The"
If the first seems to heavyweight, you could also replace the virtual method with a Func<string> dependency for your controller and use the "Configure" method to inject a specification specific one for your spec.
HTH,
Bjoern
If you're testing a controller, then perhaps you shouldn't be creating mocks or fakes of that controller. Otherwise you're just testing a mock and the test doesn't really have any validity.
Mock or fake the dependencies of the controller. Test the real controller.
In the end I ended up pulling this test out of Machine.Fakes and put it into a regular unit test. Then I just used Moq directly to configure the HttpRequestBase to seed data I needed and then just manually created my controller class and invoked methods on it.
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