What is the purpose of unit testing an interface repository - c#

I am unit testing an ICustomerRepository interface used for retrieving objects of type Customer.
As a unit test what value am I gaining by testing the ICustomerRepository in this manner?
Under what conditions would the below test fail?
For tests of this nature is it advisable to do tests that I know should fail? i.e. look for id 4 when I know I've only placed 5 in the repository
I am probably missing something obvious but it seems the integration tests of the class that implements ICustomerRepository will be of more value.
[TestClass]
public class CustomerTests : TestClassBase
{
private Customer SetUpCustomerForRepository()
{
return new Customer()
{
CustId = 5,
DifId = "55",
CustLookupName = "The Dude",
LoginList = new[]
{
new Login { LoginCustId = 5, LoginName = "tdude" },
new Login { LoginCustId = 5, LoginName = "tdude2" }
}
};
}
[TestMethod]
public void CanGetCustomerById()
{
// arrange
var customer = SetUpCustomerForRepository();
var repository = Stub<ICustomerRepository>();
// act
repository.Stub(rep => rep.GetById(5)).Return(customer);
// assert
Assert.AreEqual(customer, repository.GetById(5));
}
}
Test Base Class
public class TestClassBase
{
protected T Stub<T>() where T : class
{
return MockRepository.GenerateStub<T>();
}
}
ICustomerRepository and IRepository
public interface ICustomerRepository : IRepository<Customer>
{
IList<Customer> FindCustomers(string q);
Customer GetCustomerByDifID(string difId);
Customer GetCustomerByLogin(string loginName);
}
public interface IRepository<T>
{
void Save(T entity);
void Save(List<T> entity);
bool Save(T entity, out string message);
void Delete(T entity);
T GetById(int id);
ICollection<T> FindAll();
}

I may be missing something but it seems like every single aspect of your test is mocked up?
Generally speaking you only mock up the objects that aren't core to the test. In this case you may use this repository as the source for a function which you expect to do something with the repository to retrieve customer #5 and perform an operation on it.
For example you may mock up a customer repository so that you can call a method that verifies the login of a user. You'd use your mock repository to prevent your unit-test from relying on a real data-source, not to test your mock repository.

Rule #1 of testing:
Know what the purpose of your test is and what it is trying to prove before you write it. If you don't know what it proves, then it's useless :)
As the other posters have correctly said, you're stubbing an interface and then calling the stub -- this doesn't prove anything about whether your production code works.
What is a stub?
Stubs are used to provide canned values to drive some aspect of the class under test. E.g. Say you have a CustomerService that has an instance of type ICustomerRepository. If you wanted to see that the CustomerService could gracefully handle an error case when the repository was empty, you would stub the ICustomerRepository's GetCustomerById method to return nothing/null/throw an exception, then ensure that the CustomerService method did the correct thing (e.g. return a customer not found result).
I.e. the stub is just a collaborator that helps you reach the particular condition/behaviour of interest. We're testing CustomerService and the stubbed ICustomerRepository merely helps us achieve our goal.
You're not the first to ask this very question :). I usually advise developers to hand-roll their test doubles at first. It helps to understand all of the interactions and what the framework is actually doing for you.

Interfaces, by definition, are just contracts, so there's no code to test. You want to write unit tests against the concrete implementation(s) of the interface, because that is where the actual execution code lives.
If there's no concrete implementation of the interface and you're just mocking a concrete implementation, then your unit test is just based on a mock. That isn't really of much value.

Your test makes no sense to me. You are testing if a preprogrammed stub is returning the values you feed it, You are not testing any real code.
Follow dcp's reply. An interface is a declaration of methods. You should test implementations of these.

Related

Writing unit tests for classes that depend on external libraries/sdks

My code consists of the following components:
1 - IMyService: interface that defines properties/methods of the class that will implement it.
2 - MyService: concrete implementation of IMyService.
public interface IMyService
{
Task<MyResult> CreateAsync(string id, string json);
}
internal class MyService : IMyService
{
private readonly ExternalService _externalService;
public class MyService(ExternalService externalService)
{
this._externalService = externalService;
}
public async Task<MyResult> CreateAsync(string id, string json)
{
ServiceResult serviceResult = await this._externalService.RunAsync(id, json);
return new MyResult(serviceResult);
}
}
MyService class depends on third party library/SDK/package called ExternalService and implements method CreateAsync.
CreateAsync method takes 2 input parameters, invokes RunAsync method on ExternalService, receives result and creates my own class from result.
Question 1)
How would I approach unit testing CreateAsync method in MyService class? Is there any value in writing unit tests for it at all since it contains no logic?
Question 2)
ExternalService has its own Exceptions that it can throw when executing RunAsync method - should I capture exceptions thrown by RunAsync (wrapping try/catch around it) and cast them to my own Exception? For example - ExternalServiceException => MyServiceException.
Mock it with Moq and Autofixture. I don't know what unit testing framework you intend to use. So I would use Xunit as an example.
If it is calls to an external service you're only interested in testing what it can return.
First create an autofixture class. This is an attribute that is necessary for our test cases. More info here
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture()
.Customize(new AutoMoqCustomization()))
{
}
}
[Theory]
[AutoMoqData]
public async Task Validate_Service_ReturnResult([Frozen]Mock<IMyService> someService, ServiceResult mockResult, SomeClass sut){
//Set up interface to return what you want.
//In this case it returns mockResult always,
//but you can edit the properties of this to be whatever best fits your test case.
someService.Setup(x => x.CreateAsync(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(mockResult);
var result = await someService.Object.CreateAsync("ree", "skee");
//The class we are actually testing
var res =sut.DoSomething("someId", "someJson")
Assert.NotNull(res);
}
The [Frozen]-attribute makes sure that the behavior of the mocked someService is identical throughout all your code.
Doing all this is argueably a lot better than "faking" your interface for each testcase. Just imagine that you want CreateAsync to return different httpcodes like 404, 200, or 500. Have fun creating a new implementation of the interface for each case. With autofixture you just have set it up in the the beginning of your testcase.
The class we want to run our tests on
public class SomeClass{
IMyService someService;
public SomeClass(IMyservice someService){
this.someService = someService
}
public async Task<string> DoSomething(string id, string json){
var res = await this.someService.CreateAsync(id, json);
if(res.HttpStatusCode == 200){
//then do bla bla bla
...
}
}
Question 1: Yes. It is definitely worth it to unit test your services. You need to see if your code handles negative results. It would suck if this was a service that crashed because a result wasn't handled properly. For example if you expected an object from the service but receives null. Then before long you will have a null reference exception and a crashed service.
Question 2: Doesn't matter. Either way exceptions should be logged. If there is something important you want logged so you can query it easily eg. HttpCode. Then please do. It depends on two things. First: Can you handle the exceptions? And second: Do you log your exceptions to some central database?

How to unit test delegate was received in base class method?

I currently have a base service class that all my services extend. This is what one of the methods look like:
protected internal virtual T PerformServiceOperationWithExceptionHandling<T>(Func<T> func)
{
try
{
return func.Invoke();
}
...
}
In the derived classes I call the method like this:
public AddGuestResponse AddGuest(AddGuestRequest addGuestRequest)
{
return PerformServiceOperationWithExceptionHandling(() => AddGuestLogic(addGuestRequest));
}
I want to test AddGuest and ensure "AddGuestLogic" is being passed as a parameter in the base method? How do I achieve this with nSubstitute and nUnit. I don't think its possible?
================================================
I ended up using the following code:
[Test]
public void AddGuest_WhenCalled_PerformsAddGuestLogicWithExceptionHandling()
{
Func<AddGuestResponse> addGuestLogic = null;
_guestService.PerformServiceOperationWithExceptionHandling(Arg.Do<Func<AddGuestResponse>>(arg => addGuestLogic = arg));
var addGuestRequest = new AddGuestRequest();
_guestService.AddGuest(addGuestRequest);
_guestService.ClearReceivedCalls();
addGuestLogic.Invoke();
_guestService.Received().AddGuestLogic(addGuestRequest);
}
The _guestService is created in my setup method as follows: Substitute.ForPartsOf();
I second Sunny Milenov's answer, but would go one step further by advising you to change your design. I have learned the hard way that many of these headaches with testing base class behavior go away when you follow the principle of composition over inheritance.
I.e., if you refactor your base class to a collaborator, which you inject into your services' constructor, you can test that in isolation and mock it in your services' tests. No worrying about testing an abstract base class or testing the same exception handling in all of your services' tests.
You would test that the collaborator correctly invokes the func in the collaborator's tests.
In the services' tests you can just mock the collaborator to return the Func's result right away:
[Test]
public void ServiceLogicIsExecuted()
{
var collaborator = Substitute.For<ICollaborator>();
//Tell the test double to return the Func's result. You'd probably want to do this in the setup method.
collaborator.PerformServiceOperation(Arg.Any<Func<int>>()).Returns(x => ((Func<int>)x[0]).Invoke());
var sut = new Service(collaborator);
var result = sut.CalculateSomething();
Assert.That(result, Is.EqualTo(99));
}
public class Service
{
private readonly ICollaborator _collaborator;
public Service(ICollaborator collaborator)
{
_collaborator = collaborator;
}
public int CalculateSomething()
{
return _collaborator.PerformServiceOperation(ExecuteLogic);
}
private static int ExecuteLogic()
{
return 99;
}
}
public interface ICollaborator
{
T PerformServiceOperation<T>(Func<T> func);
}
Short answer - you shouldn't. Unit testing is about testing the behavior of the tested method, not the implementation details.
Long answer:
It doesn't matter how the class internally works, as far as it produces the expected results.
You need to test your public method on the final class and see if this works as expected. Testing a base/abstract class in isolation proves nothing.

moq a class that IS derived from the same interface as the one being moq'd

I am new to the whole MOQ movement... which by the way is pretty cool ... and I am mocking all kinds of stuff now..
Anyway, I ran into this scenario and was wondering how to go about mocking it up.
I have an class that implements the interface that I want to mock:
public interface ImyInterface
{
void doit();
}
public abstract class myBase<TChannel> : ICommunicationObject, IDisposable where TChannel : class
{
protected TChannel Channel { get; private set; }
// ICommunicationObject implementation not shown
}
public class myIIntClass : myBase<ImyInterface>, ImyInterface
{
public myIIntClass()
{
}
public void doit()
{
Channel.doit();
}
}
I think my moq test doesn't mock anything... but I am unsure and hoping to get some insight on how to either write it correctly or refactor my class:
Here is my current MOQ test:
MyClass myClass = null;
Mock<ImyInterface> moq = new Mock<ImyInterface>();
moq.Setup(x => x.doit());
myClass = (MyClass)moq.Object;
myClass.doit();
moq.VerifyAll();
Thanks from one moqer to another... :-)
I feel like maybe you're missing the point of mocking here. You mock dependencies that exist in a unit of work you're testing. So, let's say I'm testing doit here in the concrete implementation of MyClass; I want to make sure it works right. Now, let's say that method has a dependency to another class; it calls a method on it that returns a boolean value. What I want to do is mock that class because I want to make sure that MyClass.doit behaves right when it returns true and when it returns false.
See, in the example above, what I've done is ensured that no other dependencies are affecting the code flow of MyClass.doit; I'm forcing MyClass.doit down a very specific path; I want to test that path.
The code you've created literally performs nothing because it just executes the mocked up method.
You don't mock/stub the unit under test. If you are testing the doIt(), you don't mock that, you mock its (or class) dependencies.

Are my NUnit tests actually running correctly?

I'm trying to be a good developer and actually right some unit tests for some code I have written.
I am using NUnit with Ninject.MockingKernel.Moq and followed the documentation on https://github.com/ninject/ninject.mockingkernel/wiki/Examples. Here is an example of what I have been working with
[TestFixture]
public class MyUnitTest
{
private readonly MoqMockingKernel _kernel;
public MyUnitTest()
{
_kernel = new MoqMockingKernel();
}
[SetUp]
public void SetUp()
{
_kernel.Reset(); // Not really sure why this is included (something to do with caching...)
}
[Test]
public void MyTest()
{
var moqService = _kernel.GetMock<IMyService>();
moqService.Setup(x=>x.MyMethod("With parameter")
.Returns(new MyObject {Id = 1, Name = "With parameter"});
var service = _kernel.Get<IMyService>();
service.MyMethod("With parameter");
moqService.VerifyAll();
}
}
Now, to my amazement this actually works but is it actually testing the logic in the code? Or is it saying when you return this method this is what will be returned?
I did a small test, MyMethod returns an object:
var method = service.MyMothod("With parameter");
Debugged the test and method.Id does in fact equal 1 so I'm 75% certain it's working but I thought it best to check with someone more knowledgeable than myself!
If your goal is to test a IMyService that you implemented elsewhere, you are doing it wrong. What you are doing is creating a mock IMyService and testing that it is correctly mocked, which achieves not much.
You should use kernel.GetMock() if you need an IFoo to test your IMyService because your implementation of IMyService takes a IFoo as a parameter of its constructor (like it is done in the example that you linked).

Does it make any sense testing this? (Repository pattern)

Getting started with TDD and the repository pattern, I'm wondering if it makes any sense testing this...
Using the repository pattern, I have this interface:
public interface ICustomerRepository
{
IList<Customer> List();
Customer Get(int id);
}
I have like 50 different entities, so 50 different repository interfaces/implementations.
My question is if it's correct to test each repository, by mocking up the interface, like:
[TestMethod]
public void List_Should_Return_Two_Customers()
{
// Arrange
var customerr = new List<Customer>();
customer.Add(new Customer());
customer.Add(new Customer());
var repository = new Mock<ICustomerRepository>();
repository.Setup(r => r.List()).Returns(customer);
// Assert
Assert.AreEqual(2, repository.Object.List().Count);
}
[TestMethod]
public void Get_Should_Return_One_Customer()
{
// Arrange
var customer = new List<Customer>();
customerr.Add(new Customer() { Id = 1 });
customerr.Add(new Customer() { Id = 2 });
var repository = new Mock<ICustomerRepository>();
repository.Setup(r => r.Get(1)).Returns(customer.Where(w => w.Id == 1).First());
// Assert
Assert.IsTrue(repository.Object.Get(1).Id == 1);
}
Does it make any sense testing a fake implementation of these interfaces? To me it does not.
No, it does not make sense. Obviously you should test only implementations, not interfaces. There is nothing to test in an interface.
The only things being tested in your examples are the mocking framework, the .NET list and some LINQ extension methods. There is no need to test those, somebody else already takes care of that.
Maybe the intention was to provide unit tests for the fact that the interface exists and has certain methods? In that case, the tests are still unnecessary. This is implicitly tested by the tests for other code that relies on the interface declaration.
You should only create an ICustomerRepository mock when you need a fake implementation in order to test other code.
Yes, it is "correct" to test each Repository. Repositories exist to abstract your database away from the code, and should be verified that they are working correctly. Your data access layer is arguably one of the most important components to test.
The others are right.
You can't test interfaces.
You are in fact testing mocks, and that doesn't make sense.
Usually I test repositories against a database, so, not so much unit testing for them.
And for testing anything above them I mock them.
Keep in mind that 50 types of entities doesn't mean 50 repositories.
Regards.
Can I propose an alternate solution...
As Simple as your Repository is (if they are all the same methods except for what they return) why don't you make a base class using Generics. Then you would only have to test the base class.
public interface IRepository<TEntity> where TEntity : class
{
IList<TEntity> List();
TEntity Get(int id);
}
public abstract class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
IList<TEntity> List()
{
//DataContext.GetTable<TEntity>().ToList();
}
TEntity Get(int id)
{
//Might have to do some magic here... you can use reflection or create
//an abstract method that the derived class must override that returns
//a delegate id selector.
}
}

Categories

Resources