stupid question possibly, first time I'm actually writing a unit test at all (shame on me). I'm using Xunit and AutoFixture.
So, I have some unit tests that I would like to run with different combinations of input data.
For example, say I'm testing my DAL and want to test the same unit test with different types of repositories (e.g. in-memory and SQL). I also need to have some other data created, which will be used both by the unit test as well as the repository.
Some of my classes need to be created via factory methods, as they don't have any public constructors.
My ideal would be do to something like
[Theory, InMemoryRepository, SomeOtherData]
[Theory, SqlRepository, SomeOtherData]
// ... some other data combinations ...
public void SomeTest(IRepository repository, ISomeOtherData someOtherData)
{
// do some tests here
}
public class InMemoryRepositoryAttribute : AutoDataAttribute
{
public InMemoryRepositoryAttribute()
{
Fixture.Register<IRepository>(CreateRepository);
}
protected IRepository CreateRepository()
{
var data = Fixture.CreateMany<ISomeOtherData>().ToList(); // this will throw an exception "AutoFixture was unable to create an instance (...)" as my binding doesn't seem be available in the Fixture
var repository = new InMemoryDAL.Repository();
repository.Insert(data);
return repository;
}
}
public class SomeOtherDataAttribute : AutoDataAttribute
{
public SomeOtherDataAttribut()
{
Fixture.Register<ISomeOtherData>(CreateData);
}
protected ISomeOtherData CreateData()
{
string test = Fixture.Create<string>();
var data = (new SomeOtherDataFactory()).Create(test);
return data;
}
}
but this doesn't work, as both my AutoDataAttribute-classes seem to be based on seperate fixtures. I.e. whatever I register in my SomeOtherDataAttribute doesn't seem to be available in my InMemoryRepositoryAttribute instance.
Is there any way to fix this & use attributes to combine different sets of data in a Fixture?
Or what alternatives would you suggest - maybe best to create individual test functions for each data combination, and call SomeTest() explicitly from there?
Thanks!
Actually, you can achieve this by defining a custom AutoDataAttribute that allows supply array of customizations types. Here is a example of how to accomplish this task:
public class CompositeCustomizationsAttribute : AutoDataAttribute
{
public CompositeCustomizationsAttribute(params Type[] customizationTypes)
{
foreach (var type in customizationTypes)
{
var customization = (ICustomization)Activator.CreateInstance(type);
Fixture.Customize(customization);
}
}
}
public class InMemoryRepositoryCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register<IRepository>(() => CreateRepository(fixture));
}
protected IRepository CreateRepository()
{
var data = Fixture.CreateMany<ISomeOtherData>().ToList();
var repository = new InMemoryDAL.Repository();
repository.Insert(data);
return repository;
}
}
public class SomeOtherDataCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register<ISomeOtherData>(() => CreateData(fixture));
}
protected ISomeOtherData CreateData()
{
string test = Fixture.Create<string>();
var data = (new SomeOtherDataFactory()).Create(test);
return data;
}
}
Given above customizations and CompositeCustomizationsAttribute you can now define your test method :
[Theory, CompositeCustomizations(typeof(InMemoryRepositoryCustomization), typeof(SomeOtherDataCustomization))]
public void SomeTest(IRepository repository, ISomeOtherData someOtherData)
{
// do some tests here
}
Related
I try to create a good testable repository class to use with Moq. I don't want duplicate my selector methods (GetAll, Get, ...). My implementation works fine but SonarSource reports an error RSPEC-1699 Does anyone know of a better implementation?
var areas = new Area[] { ... };
var areaRepositoryMock = new Mock<BaseAreaRepository>() { CallBase = true };
areaRepositoryMock.Setup(m => m.Initialize()).Returns(areas);
Base Class
public abstract class BaseAreaRepository
{
protected Area[] _areas;
protected BaseAreaRepository()
{
this._areas = this.Initialize();
}
public abstract Area[] Initialize();
public Area[] GetAll()
{
return this._monitoredAreas;
}
public Area Get(int id)
{
return this._areas.FirstOrDefault(o => o.Id.Equals(id));
}
}
MyAreaRepository
public class MyAreaRepository : BaseAreaRepository
{
public override Area[] Initialize()
{
return //Load data from an other source
}
}
The RSPEC-1699 Constructors should only call non-overridable methods doens't have anything with the unit tests it will remain there regardless how you are going to test it.
Does anyone know of a better implementation?
I would like to propose another approach in order to avoid this violation and make your code even more testable.
The idea is instead of the base class use composition and DI principle.
public interface IAreaContext
{
Area[] GetAreas();
}
public class AreaRepository
{
private IAreaContext _areaContext;
protected BaseAreaRepository(IAreaContext areaContext)
{
_areaContext = areaContext;
}
public Area[] GetAll()
{
return _areaContext.GetAreas();
}
}
Then you could define multiple implementations of IAreaContext and injext:
public class MyAreaContext : IAreaContext
{
public Area[] GetAreas()
{
return //Load data from an other source
}
}
public class MyOtherAreaContext : IAreaContext
{
public Area[] GetAreas()
{
return //Load data from an other source
}
}
Now when you have this setup repository could be easily testable for different behaviors of the context itself. This is just an example to demonstrate idea:
//Arrange
var context = new Mock<IAreaContext>();
context.Setup(m => m.GetAreas()).Verifiable();
var sut = new AreaRepository(context.Object);
//Act
var _ = sut.GetAll();
//Assert
context.Verify();
If you want to test just the base class, then I would create a unit test specific implementation of the class, and just provide any helper functions to test the protected ones. Basically what you have done with MyAreaRepository but as a private class within the test class.
Summary
I'm currently writing some integration code so that I can interact with an accounting system.
The accounting system in question is Acceo Acomba, using its SDK which turns to be distributed COM objects.
I have written a generic class that serves the purpose of a generic repository for any given Acomba entity.
public abstract class AcombaRepository<TEntity, TNativeRepository>
where TEntity : class
where TNativeRepository : IBaseDataKey {
public AcombaRepository( TNativeRepository nativeRepository, IMapper entityMapper ) {
// Guard clauses...
NativeRepository = nativeRepository;
this.entityMapper = entityMapper;
}
protected readonly TNativeRepository NativeRepository;
public TEntity Create( TEntity toCreate ) {
NativeRepository.ReserveCardNumber(); // Insert
entityMapper.Map( toCreate, NativeRepository ); // Assigning props
NativeRepository.AddCard(); // Save or commit to Acomba
}
}
IBaseDataKey
This interface is the base entity for any given accessible entity within the system. In order to make sure I have access to its basics, I put this type constraint on my generic repository.
AcombaProductsRepository
This is the code under test which actually use the base method as-is.
public class AcombaProductsRepository : AcombaRepository<MyProduct, IProduct022> {
public AcombaPRoductsRepository( IProduct022 nativeRepository, IMapper productMapper )
: base( nativeRepository, productMapper ) {
}
}
Unit Testing
In order to make sure that my code uses the Acomba SDK adequately to create a new entity within the Acomba underlying data store, I verify that certain steps are strictly respected.
public class AcombaProductsRepositoryTests {
private readonly Mock<IProduct022> nativeRepositoryMock;
private readonly AcombaProductsRepsoitory sut;
public AcombaProductsRepositoryTests() {
nativeRepositoryMock = new Mock<IProduct022>();
sut = new AcombaProductsRepository( nativeRepositoryMock.Object );
}
[Fact]
public void Create_Should_Reserve_A_Card_Number() {
var toCreate = new MyProduct();
nativeRepositoryMock.Setup( r => r.ReserveCardNumber() ).Verifiable();
sut.Create( toCreate );
nativeRepositoryMock.Verify( r => r.ReserveCardNumber() );
}
}
Here, although the interface IProduct022 derives from IBaseDataKey, Moq states that the expected invocation
IProduct022.ReserveCardNumber
was never performed. Besides, it also states that the performed invocation was
IBaseDataKey.ReserveCardNumber
For the essence of the unit test itself, it doesn't actually matter whether the performed invocation was either, as long as the ReserveCardNumber is called upon.
How to make this test pass?
Further Details (edit)
Here's the error message from the test result.
As I take it, Moq performs the invocation of the base IBaseDataKey class instead of the IProduct022 derived one because of the type constraint, I suspect.
The following minimal example was used based on the provided OP
public class AcombaProductsRepository : AcombaRepository<MyProduct, IProduct022> {
public AcombaProductsRepository(IProduct022 nativeRepository)
: base(nativeRepository) {
}
}
public abstract class AcombaRepository<TEntity, TNativeRepository>
where TEntity : class
where TNativeRepository : IBaseDataKey {
public AcombaRepository(TNativeRepository nativeRepository) {
NativeRepository = nativeRepository;
}
protected readonly TNativeRepository NativeRepository;
public TEntity Create(TEntity toCreate) {
NativeRepository.ReserveCardNumber(); // Insert
NativeRepository.AddCard(); // Save or commit to Acomba
return toCreate;
}
}
The following minimal assumptions were made of the interface and entities used as they were not provided in the OP
public interface IBaseDataKey {
void ReserveCardNumber();
void AddCard();
}
public interface IProduct022 : IBaseDataKey {
}
public class MyProduct {
}
The following Test was exercised based on the information provided in the OP and using MSTest and the latest version of Moq
[TestClass]
public class AcombaProductsRepositoryTests {
private readonly Mock<IProduct022> nativeRepositoryMock;
private readonly AcombaProductsRepository sut;
public AcombaProductsRepositoryTests() {
nativeRepositoryMock = new Mock<IProduct022>();
sut = new AcombaProductsRepository(nativeRepositoryMock.Object);
}
[TestMethod]
public void _Create_Should_Reserve_A_Card_Number() {
//Arrange
var toCreate = new MyProduct();
nativeRepositoryMock.Setup(r => r.ReserveCardNumber()).Verifiable();
//Act
sut.Create(toCreate);
//Asert
nativeRepositoryMock.Verify(r => r.ReserveCardNumber());
}
}
The test when exercised passed without exception.
I suggest a review of original code as issue as currently presented is not reproducible.
I have implemented array based Stack Data Structure along with corresponding Unit Tests. This Stack implements my IStack interface. So at the moment, my UT class looks something like that:
[TestClass]
public class Stack_ArrayBased_Tests
{
//check against empty collection
[TestMethod]
public void IsEmpty_NoElements()
{
var myStack = new Stack_ArrayBased_Example1(10);
var exp = true;
var act = myStack.IsEmpty();
Assert.AreEqual(exp, act);
}
Now, I am about to implement Linked List based Stack. This Stack will inherit from the same IStack interface.
I would like to Unit Test the linked list Stack as well. Since both are inheriting from the same interface, I should be able to take advantage of already implemented Unit Test, in order to prevent from unnecessary code duplication.
What would be the best way to create two separate Unit Test classes, one for Array based Stack, and another for Linked List based Stack, that would use the same Unit Test methods? I assume Dependency Injection would be an answer, but how I would go about it?
Dependency injection is never the answer when it comes to tests.
You are not testing abstractions, that's impossible, you test concrete implementations. You can however mock abstractions, interfaces, abstract classes.
You can create some class with the sole purpose of reusing code and you call that class from your test methods, that's ok and totally doable.
You will still need two test classes, one for each of your concrete implementations, and have both call this new class you created. This avoids code duplication.
You can separate logic in another method.
[TestMethod]
public void IsEmpty_NoElements_ArrayBased()
{
var myStack = new Stack_ArrayBased_Example1(10);
IsEmpty_NoElements(myStack)
}
[TestMethod]
public void IsEmpty_NoElements_LinkedListBased()
{
var myStack = new Stack_LinkedListBased_Example1(10);
IsEmpty_NoElements(myStack)
}
public void IsEmpty_NoElements(IStack myStack)
{
var exp = true;
var act = myStack.IsEmpty();
Assert.AreEqual(exp, act);
}
Say we have the following
public interface IStack
{
bool IsEmpty { get; }
}
public class StackImpl1 : IStack
{
public StackImpl1(int size)
{
IsEmpty = true;
}
public bool IsEmpty { get; }
}
public class StackImpl2 : IStack
{
public StackImpl2(int size)
{
IsEmpty = true;
}
public bool IsEmpty { get; }
}
And we wish to implement the IsEmpty_OnCreation() test from the OP. We can make a common test and add multiple invokers (one for each implementation to be tested). The problem is scaling.
For each new piece of functionality to be tested we need to add
1) the test implementation
2) an invoker for each implementation to be tested.
For each new implementation we introduce, we need to add an invoker for each existing test.
It is possible to use inheritance to do most of the work for us
public abstract class StackTest
{
protected abstract IStack Create(int size);
[TestMethod]
public void IsEmpty_NoElements()
{
var myStack = Create(10);
var exp = true;
var act = myStack.IsEmpty;
Assert.AreEqual(exp, act);
}
}
[TestClass]
public class StackImp1Fixture : StackTest
{
protected override IStack Create(int size)
{
return new StackImpl1(size);
}
}
[TestClass]
public class StackImp2Fixture : StackTest
{
protected override IStack Create(int size)
{
return new StackImpl2(size);
}
}
The tests are generated in each derived fixture.
If we want to add a new test, we add it to the StackTest class and it is automatically included in each derived fixture.
If we add a third implementation of IStack , we simply add a new test fixture deriving from StackTest and overriding the create method.
Note:
If the classes under test have default constructors, the same shape can be used with a Generic StackTest as the base
public class GenStackTest<TStack> where TStack : IStack, new()
{
[TestMethod]
public void IsEmpty_NoElements()
{
var myStack = new TStack();
var exp = true;
var act = myStack.IsEmpty;
Assert.AreEqual(exp, act);
}
}
[TestClass]
public class GenStack1Fixture : GenStackTest<StackImpl1>
{
}
[TestClass]
public class GenStack2Fixture : GenStackTest<StackImpl2>
{
}
I have a controller which contains a business class that internally has dependencies to a datahandler. For testing that business class I need to mock the datahandler. After setup, I am assigning the business class' datahandler with the mocked datahandler. But while debugging, the business class' datahandler is showing null , I know that I should use the constructor to inject the mocked object.But is it possible to do it without using any constructor injection ?Can any body help me with this?
my business class:
public class FooBusiness
{
public static BarDataHandler _barDatahandler = new BarDataHandler();
...
}
Test class:
public class FooBusinessTest
{
...
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x=>x.Search(It.IsAny<int>).Returns(1);
...
FooBusiness _fooBusiness = new FooBusiness();
FooBusiness._barDatahandler = _mockedBarDataHandler.Object;
//Act
...
}
}
As I mentioned, there are multiple ways to achieve your needs.
Personally I like Shyju's answer more (Constructor Injection), but if you can't change the constructor, you can still change the implementation afterwards by setting the property:
business class:
public class FooBusiness
{
private IBarDataHandler _barDatahandler = new BarDatahandler();
public IBarDataHandler BarDatahandler
{
get { return _barDatahandler; }
set { _barDatahandler = value; }
}
public int Search(int a)
{
return _barDatahandler.Search(a);
}
}
Test class:
public class FooBusinessTest
{
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x => x.Search(It.IsAny<int>).Returns(1);
FooBusiness fooBusiness = new FooBusiness();
fooBusiness.BarDatahandler = _mockedBarDataHandler.Object;
//Act
}
}
If you worry about to refactor the implementation, it is better to setup all the tests first. After that you can refactor with a safer feeling :)
You need to inject your dataHandler dependency to FooBusiness
You need to extract an interface for your BarDataHandler if one does not exist.
interface IBarDataHandler
{
string GetUserToken(int id);
}
public class BarDataHandler : IBarDataHandler
{
public string GetUserToken(int id)
{
// to do :read from db and return
}
}
And add a constructor to FooBusiness class which accepts an implementation of IBarDataHandler.
public class FooBusiness
{
IBarDataHandler barDataHandler;
public FooBusiness(IBarDataHandler barDataHandler)
{
this.barDataHandler=barDataHandler
}
public string GetUserToken(int id)
{
return this.barDataHandler.GetUserToken(id);
}
}
You can use any one of the dependency injection frameworks like Unity/Ninject/StructureMap to resolve your concrete implementation when your app runs.
You can use any mocking framework like Moq to mock the fake implementation of IBarDataHandler in your unittests.
I'm using moq.dll
When I mock a class(all the IRepository interface) i use this line code
int state = 5;
var rep = new Mock<IRepository>();
rep.Setup(x => x.SaveState(state)).Returns(true);
IRepository repository = rep.Object;
but in this case i mock all the function in repository class.
Then all the methods in class repository are substituted with the methods setup of Mock dll
I want use all the methods defined in class repository(the real class) and mock only one function(SaveState)
How can I do this? Is possible?
You can create an instance of the real repository, then use the As<>() to obtain the desired interface, which you can then override with the setup, like this:
var mockRep = new Mock<RealRepository>(ctorArg1, ctorArg2, ...)
.As<IRepository>();
mockRep.Setup(x => x.SaveState(state)).Returns(true);
Then mockRep.Object as the repository dependency to the class under test.
Note that you will only be able to Mock methods on the Interface*, or virtual methods, in this way.
Update : *This might not work in all scenarios, since .Setup will only work on virtual methods, and C# interface implementations are "virtual" and sealed by default. And using As() will prevent the partial mock behaviour.
So it appears that the RealRepository concrete class will need to implement the IRepository interface with virtual methods in order for the partial mock to succeed, in which case CallBase can be used for the wire-up.
public interface IRepo
{
string Foo();
string Bar();
}
public class RealRepo : IRepo
{
public RealRepo(string p1, string p2) {Console.WriteLine("CTOR : {0} {1}", p1, p2); }
// ** These need to be virtual in order for the partial mock Setups
public virtual string Foo() { return "RealFoo"; }
public virtual string Bar() {return "RealBar"; }
}
public class Sut
{
private readonly IRepo _repo;
public Sut(IRepo repo) { _repo = repo; }
public void DoFooBar()
{
Console.WriteLine(_repo.Foo());
Console.WriteLine(_repo.Bar());
}
}
[TestFixture]
public class SomeFixture
{
[Test]
public void SomeTest()
{
var mockRepo = new Mock<RealRepo>("1st Param", "2nd Param");
// For the partially mocked methods
mockRepo.Setup(mr => mr.Foo())
.Returns("MockedFoo");
// To wireup the concrete class.
mockRepo.CallBase = true;
var sut = new Sut(mockRepo.Object);
sut.DoFooBar();
}
}
I came to this page because I had exactly the same problem: I needed to mock a single method, which was relying on many external sources and could produce one of three outputs, while letting the rest of the class do its work. Unfortunately the partial mock approach proposed above did not work. I really don't know why it did not work. However, the main problem is that you can't debug inside such mocked class even if you put break points where you want. This is not good because you might really need to debug something.
So, I used a much simpler solution: Declare all methods that you want to mock as virtual. Then inherit from that class and write one-liner mock overrides to return what you want, for example:
public class Repository
{
/// <summary>
/// Let's say that SaveState can return true / false OR throw some exception.
/// </summary>
public virtual bool SaveState(int state)
{
// Do some complicated stuff that you don't care about but want to mock.
var result = false;
return result;
}
public void DoSomething()
{
// Do something useful here and assign a state.
var state = 0;
var result = SaveState(state);
// Do something useful with the result here.
}
}
public class MockedRepositoryWithReturnFalse : Repository
{
public override bool SaveState(int state) => false;
}
public class MockedRepositoryWithReturnTrue : Repository
{
public override bool SaveState(int state) => true;
}
public class MockedRepositoryWithThrow : Repository
{
public override bool SaveState(int state) =>
throw new InvalidOperationException("Some invalid operation...");
}
That's all. You can then use your mocked repos during unit tests AND you can debug anything you need. You can even leave the protection level below public so that not to expose what you don't want to expose.