Reduce duplication in NUnit tests for different implementations of interface - c#

I have the following interface:
public interface IStack
{
int Peek();
void Push(int i);
}
And two implementations:
public class LinkedListStack : IStack
{
public void Push(int x)
{
...
}
public int Peek()
{
...
}
}
public class ArrayStack : IStack
{
public void Push(int i)
{
...
}
public int Peek()
{
...
}
}
For my unit tests - I currently have something like this, two files containing the same tests - the only difference being the implementation:
LinkedListStackTest.cs:
public class LinkedListStackTest
{
[Test]
public void PushToStack()
{
//Arrange
IStack stack = new LinkedListStack();
//Act
stack.Push(1);
//Assert
Assert.AreEqual(1, stack.Peek());
}
}
ArrayStackTest.cs
public class ArrayStackTest
{
[Test]
public void PushToStack()
{
//Arrange
IStack stack = new ArrayStack();
//Act
stack.Push(1);
//Assert
Assert.AreEqual(1, stack.Peek());
}
}
Given the tests for the implementations should be the same - is there a way I can write a single set of NUnit tests that will run against all my implementations of IStack?

You can use the TestCaseSourceAttribute:
[Test]
[TestCaseSource(typeof(StackTestCases))]
public void PushToStack(IStack stack)
{
//Arrange/Act
stack.Push(1);
//Assert
Assert.AreEqual(1, stack.Peek());
}
Implementation of StackTestCases:
internal class StackTestCases : IEnumerable
{
public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new LinkedListStack());
yield return new TestCaseData(new ArrayStack());
}
}
/// <inheritdoc />
public IEnumerator GetEnumerator()
{
return TestCases.GetEnumerator();
}
}
Please note that the test method will take an IStack as a parameter:
[Test]
[TestCaseSource(typeof(StackTestCases))]
public void PushToStack(IStack stack)
...And you can return the different implementations of IStack in TestCases property of StackTestCases:
yield return new TestCaseData(new LinkedListStack());
yield return new TestCaseData(new ArrayStack());

You will have to use generics for this purpose with TextFixture attributes having the implementations of your interface.
[TestFixture(typeof(LinkedListStack))]
[TestFixture(typeof(ArrayStack))]
class IStack_Contract<T> where T : IStack, new()
{
}
You just pass the types to your tests and then they will execute for the respective implementations.

You can use abstract classes to achieve this.
First, create an abstract class where you will define all your common/share tests among all your implementations:
public abstract class MyClassShould
{
protected abstract MyInterface Initialize();
protected MyInterface myInterface;
[SetUp]
public void SetUp()
{
myInterface = Initialize();
}
[Test]
public void FirstTest()
{
// do something with myInterface
// assert results
}
}
Then create a test class for your Implemenetation1
public abstract class MyFirstImplementationShould
{
protected override MyInterface Initialize()
{
return new MyFirstImplementation();
}
}
And the same for your Implementation2 which may have extra tests. For example, this implementation has a TTL expiration while the first one doesn't.
public abstract class MySecondImplementationShould
{
protected override MyInterface Initialize()
{
return new MySecondImplementation();
}
[Test]
public void TtlTest()
{
// do something with myInterface
// assert results
}
}

Related

Decorate even derived types or how to intercept all calls to a specific method

I want to decorate all created instances, that are derived from a specific interface.
public interface IInterface
{
void Execute(); //// only this shall be intercepted
}
public interface IDerivedInterface : IInterface
{
bool CanExecute { get; } //// this shall not be intercepted
}
public class DirectImplementation : IInterface
{
public void Execute()
{
}
}
public class DerivedImplementation : IDerivedInterface
{
public void Execute()
{
}
public bool CanExecute { get; }
}
public class Decorator : IInterface
{
public Decorator(IInterface inner)
{
Inner = inner;
}
public IInterface Inner { get; }
public void Execute()
{
Console.WriteLine("Something is executed");
Inner.Execute();
}
}
My expectation is implemented in this unit test
[Test]
public void Should_know_how_structure_map_works()
{
var container = new Container(
c =>
{
c.For<IInterface>().Use<DirectImplementation>();
c.For<IDerivedInterface>().Use<DerivedImplementation>();
c.For<IInterface>().DecorateAllWith<Decorator>();
});
var interfaceImpl = container.GetInstance<IInterface>();
var derivedInterfaceImpl = container.GetInstance<IDerivedInterface>();
Assert.That(interfaceImpl, Is.TypeOf<Decorator>());
Assert.That(((Decorator)interfaceImpl).Inner, Is.TypeOf<DirectImplementation>());
Assert.That(derivedInterfaceImpl, Is.TypeOf<Decorator>());
Assert.That(((Decorator)derivedInterfaceImpl).Inner, Is.TypeOf<DerivedImplementation>());
}
But this can obviously not be full filled, since Decorator does not implement IDerivedInterface. So my question is:
Is there any way, to configure StructureMap in such a way, that i can intercept all calls to IInterface.Execute?

Create a full TestSuite per interface or per Implementation

I was wondering about what is the best practices to write tests if I have multiple implementations per interface.
Have I to replicate each test per implementations or I can create an abstract class that contains all tests about the interface and then create a simple test class per implementation that extends my abstract test class?
I am following "The art of unit testing" written by Osherove and he always repeat that we have to keep tests, and test suites, as simple as we can, so I don't know if adding an abstract class will increase the complexity of read tests by other developers.
Which one of the following example is commonly accepted and more readable?
Sample code:
public interface IMyInterface()
{
public string MyMethod(string input);
}
public class MyClassA : IMyInterface
{
public string MyMethod(string input)
{
return input;
}
}
public class MyClassB : IMyInterface
{
public string MyMethod(string input)
{
return "hello from MyClassB";
}
}
public class MyClassC : IMyInterface
{
public string MyMethod(string input)
{
throw new NotImplementedException();
}
}
TestSuite 1:
[TestFixture]
public class MyClassATest {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
MyClassA sut = new MyClassA();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
[TestFixture]
public MyClassBTest {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
MyClassA sut = new MyClassB();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
[TestFixture]
public MyClassCTest {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
MyClassA sut = new MyClassC();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
TestSuite 2:
[TestFixture]
public abstract class IMyInterfaceTest<TImplementation> where TImplementation : IMyInterface {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
TImplementation sut = new MyClassC();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
[TestFixure]
public class MyClassATest : IMyInterfaceTest<MyClassA> {}
[TestFixure]
public class MyClassATest : IMyInterfaceTest<MyClassB> {}
[TestFixure]
public class MyClassATest : IMyInterfaceTest<MyClassC> {}
Why not try this approach using TestCaseSource (https://github.com/nunit/docs/wiki/TestCaseData). The advantage being you have one test instead of many repeating tests that do the same thing.
[TestCaseSource(typeof(MyDataClass), "TestCases")]
public void MyMethod_WhenCalled_ReturnsANotNullString(IMyInterface sut, string value)
{
//arrange
//act
string result = sut.MyMethod(value);
//assert
Assert.IsNotNull(result);
}
public class MyDataClass
{
public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new MyClassA(), "hi");
yield return new TestCaseData(new MyClassB(), "test");
yield return new TestCaseData(new MyClassC(), "another");
}
}
}

Optimize my Code logic without singletion

public interface IHandler
{
List<string> Run();
}
public class Base
{
void methodA();
}
public Class Der1 : Base , IHandler
{
List<string> Run()
{ //Generate huge records
}
}
public Class Der2 : Base , IHandler
{
List<string> Run()
{//Generate huge records
}
}
public Class Der3 : Base , IHandler
{
List<string> Run()
{//Generate huge records
}
}
Currently Run() is getting executed across all the derived class and generating same set of records. I want this to optimize.
Move the RecordGeneration process inside Run() to a common class/function and get executed once and prepare the necessary records. All the Derived class will use this "RecordGeneration" to get the already Generated Records.
Note: I cannot implement Singleton pattern.
You can use Lazy<T>:
private Lazy<List<string>> l;
public Der1
{
l = new Lazy<List<string>>(() => Run());
}
public List<string> ResultOfRun
{
get
{
return l.Value();
}
}
To extend on my initial answer, if the method has the same output across all methods, you can do this:
public class Base
{
private Lazy<List<string>> l = new Lazy<List<string>>(() => RunStatic());
private static List<string> RunStatic()
{
//
}
public List<string> ResultOfRun
{
get
{
return l.Value();
}
}
void methodA();
}
Then you only have to call it in Run, which could be in the base class to if it implements the interface:
public Class Der1 : Base , IHandler
{
List<string> Run()
{
return this.ResultOfRun;
}
}

How to mock a class that implements multiple interfaces

How to mock the following class:
UserRepository : GenericRepository<User>, IUserRepository
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
I am using Moq, and I am confused how to handle multiple interfaces correctly.
Take a look at https://github.com/Moq/moq4/wiki/Quickstart
Advanced Features
// implementing multiple interfaces in mock
var foo = new Mock<IFoo>();
var disposableFoo = foo.As<IDisposable>();
// now IFoo mock also implements IDisposable :)
disposableFoo.Setup(df => df.Dispose());
There is a mechanism built into Moq for dealing with multiple interfaces.
Say we have an interface IFoo and an implementation of the same Foo. We also have ClientOne that uses IFoo.
We then have an interface IFooBar : IFoo, an implementation FooBar : Foo, IFooBar and a ClientTwo that uses IFooBar.
When creating an end-to-end test for the system we have an IFooBar, ClientOne and ClientTwo. The As<>() function allows us to use the Mock<IFooBar> as a Mock<IFoo>.
public interface IFoo {
int Id { get; }
}
public class Foo : IFoo {
public int Id {
get { return 1; }
}
}
public interface IFooBar : IFoo {
string Name { get; }
}
public class FooBar : Foo, IFooBar {
public string Name {
get { return "AName"; }
}
}
public class ClientOne {
private readonly IFoo foo;
public ClientOne(IFoo foo) {
this.foo = foo;
}
public string Details {
get { return string.Format("Foo : {0}", foo.Id); }
}
}
public class ClientTwo {
private readonly IFooBar fooBar;
public ClientTwo(IFooBar fooBar) {
this.fooBar = fooBar;
}
public string Details {
get { return string.Format("Foo : {0}, Bar : {1}", fooBar.Id, fooBar.Name); }
}
}
[TestMethod]
public void TestUsingBothClients() {
var fooBarMock = new Mock<IFooBar>();
var fooMock = fooBarMock.As<IFoo>();
fooBarMock.SetupGet(mk => mk.Id).Returns(1);
fooBarMock.SetupGet(mk => mk.Name).Returns("AName");
var clientOne = new ClientOne(fooMock.Object);
var clientTwo = new ClientTwo(fooBarMock.Object);
Assert.AreEqual("Foo : 1", clientOne.Details);
Assert.AreEqual("Foo : 1, Bar : AName", clientTwo.Details);
}
If I understand the question correctly, you want have a single mock instance of UserRepository, and for the purposes of a test, setup calls to methods from both the IGenericRepository<TEntity> interface and the IUserRepository interface.
You can implement multiple interfaces with a single mock instance like this:
var genericRepositoryMock = new Mock<IGenericRepository<User>>();
genericRepositoryMock.Setup(m => m.CallGenericRepositoryMethod()).Returns(false);
var userRepositoryMock = genericRepositoryMock.As<IUserRepository>();
userRepositoryMock.Setup(m => m.CallUserRepositoryMethod()).Returns(true);
However, as D Stanley pointed out, the need to do this is probably an indication that there is a flaw in your design.
You can spare a bit with declaring a common interface just for testing, like:
interface IA { void Work(); }
interface IB { void Rest(); }
class AB: IA, IB
{
public void Work() { ... }
public void Rest() { ... }
}
interface IABTest : IA, IB
{}
class SomeTest
{
public void DoTest()
{
var ab = new Mock<IABTest>();
ab.Setup(m => m.Work());
ab.Setup(m => m.Rest());
}
}

How to moq a property that will be indirectly modified?

I am trying to do a very simple thing: Set an initial value to a property, call a method which callback should modify the property value, and read the property at the end.
Class Test2 is using ITest1 to automatize some actions.
public interface ITest1
{
decimal Value { get; set; }
void Increment();
}
public class Test2
{
ITest1 test1;
public Test2(Itest1 test1)
{
this.test1 = test1;
}
public void Increment()
{
this.test1.Increment();
}
public Get()
{
return this.test1.Value;
}
}
In order to achieve this behaviour I setted up this test:
[TestClass]
public class Test2Test
{
private Test2 test2;
private decimal value;
[TestInitialize]
public void Setup()
{
var test1Mock = new Mock<ITest1>();
test1Mock.SetupGet(m => m.Value).Returns(value);
test1Mock
.Setup(m => m.Increment())
.Callback(() => value++);
this.test2= new Test2(test1Mock.Object);
}
[TestMethod]
public void Get_Returns0()
{
Assert.AreEqual(0, this.test2.Get());
}
[TestMethod]
public void Get_AfterIncrement_Returns1()
{
this.test2.Increment();
Assert.AreEqual(1, this.test2.Get());
}
}
The second test is returning always 0. Why is this happening?
The solution is to return actions instead of variables as:
.Return(() => value) instead of .Return(value)
Answer found here.

Categories

Resources