Create a full TestSuite per interface or per Implementation - c#

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");
}
}
}

Related

Testing Code with Third Party Object Instantiation

New to unit testing and trying to get my head around some simple tests for a piece of code which gets or creates a template if it doesn't exist (in Umbraco 8).
The method is quite simple, when Initialise is called, it gets the template and if it doesn't exist, creates it:
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Components
{
public class TemplateComponent : IComponent
{
private readonly IFileService _fileService;
public TemplateComponent(IFileService fileService)
{
_fileService = fileService;
}
public void Initialize()
{
ITemplate blogTemplate = _fileService.GetTemplate("aldusBlog");
if (blogTemplate == null)
{
blogTemplate = new Template("Aldus Blog", "aldusBlog");
_fileService.SaveTemplate(blogTemplate);
}
}
public void Terminate() { }
}
}
Works okay, no problem.
I'm trying to write a few tests, the first checks if _fileService.GetTemplate is called.
The second test should check that _fileService.SaveTemplate() is called if that returns null.
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Components;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Components
{
[TestFixture]
public class TemplateComponentTests
{
private Mock<IFileService> _fileService;
private TemplateComponent _component;
[SetUp]
public void SetUp()
{
_fileService = new Mock<IFileService>();
_component = new TemplateComponent(_fileService.Object);
}
[Test]
public void Initialise_WhenCalled_GetsBlogTemplate()
{
_component.Initialize();
_fileService.Verify(s => s.GetTemplate("aldusBlog"), Times.Once);
}
[Test]
public void Initialise_BlogTemplateDoesNotExist_CreateTemplate()
{
_fileService
.Setup(s => s.GetTemplate("aldusBlog"))
.Returns((ITemplate) null);
_component.Initialize();
_fileService.Verify(s => s.SaveTemplate(It.Is<ITemplate>(p => p.Alias == "aldusBlog"), -1), Times.Once());
}
}
}
The trouble when I do this is that the blogTemplate = new Template("Aldus Blog", "aldusBlog"); throws an error:
Can not get Current.Config during composition. Use composition.Config.
I assume this is because I don't have any kind of context which leads me to think that the ITemplate needs to be mocked. However, because new Template("Aldus Blog", "aldusBlog"); will always be called, it will always throw this error.
Obviously the code isn't bullet proof, so how do I refactor this to be testable?
That 3rd party class is probably tightly coupled to an implementation concern that does not exist or is not configured when unit testing in isolation.
abstract that object creation out into a factory.
public interface ITemplateFactory {
ITemplate Create(string name, string alias);
}
whose implementation can be injected at run-time
public class DefaultTemplateFactory : ITemplateFactory {
public ITemplate Create(string name, string alias) {
return new Template(name, alias);
}
}
Provided it is registered at the composition root during startup
This now allow the component to be loosely coupled away from implementation concerns
public class TemplateComponent : IComponent {
private readonly IFileService fileService;
private readonly ITemplateFactory templateFactory;
public TemplateComponent(IFileService fileService, ITemplateFactory templateFactory) {
this.fileService = fileService;
this.templateFactory = templateFactory;
}
public void Initialize() {
ITemplate blogTemplate = fileService.GetTemplate("aldusBlog");
if (blogTemplate == null) {
blogTemplate = templateFactory.Create("Aldus Blog", "aldusBlog");
fileService.SaveTemplate(blogTemplate);
}
}
public void Terminate() { }
}
That can be replaced as needed when testing in isolation
[TestFixture]
public class TemplateComponentTests {
private Mock<IFileService> fileService;
private Mock<ITemplateFactory> templateFactory;
private TemplateComponent component;
string templateAlias = "aldusBlog";
[SetUp]
public void SetUp() {
//Arrange
fileService = new Mock<IFileService>();
templateFactory = new Mock<ITemplateFactory>();
templateFactory.Setup(_ => _.Create(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string name, string alias) =>
Mock.Of<ITemplate>(_ => _.Alias == alias && _.Name == name)
);
component = new TemplateComponent(fileService.Object, templateFactory.Object);
}
[Test]
public void Initialise_WhenCalled_GetsBlogTemplate() {
//Act
component.Initialize();
//Assert
fileService.Verify(s => s.GetTemplate(templateAlias), Times.Once);
}
[Test]
public void Initialise_BlogTemplateDoesNotExist_CreateTemplate() {
//Act
component.Initialize();
//Assert
fileService.Verify(s => s.SaveTemplate(It.Is<ITemplate>(p => p.Alias == templateAlias), 0), Times.Once());
}
}

Reduce duplication in NUnit tests for different implementations of interface

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
}
}

C# Mock using Moq

I have a Employee class with one method which is not implemented
namespace Employee
{
public class Employee
{
public virtual DateTime getDateOfJoining(int id)
{
throw new NotImplementedException();
}
}
}
I want to mock this, and I'm expecting the method to return current DateTime.
namespace Employee.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void getJoiningDateMock()
{
var employee = new Mock<Employee>();
employee.Setup(x => x.getDateOfJoining(It.IsAny<int>())).Returns((int x) => DateTime.Now);
var objEmp = new Employee();
Assert.AreEqual(DateTime.Now, employee.getDateOfJoining(1));
}
}
}
The way I'm invoking Mock is incorrect. What am I missing here, specifically how would I write AssertEquals?
The below only confirms that the mock behaves as it was setup.
[TestClass]
public class UnitTest1 {
[TestMethod]
public void getJoiningDateMock() {
//Arrange
var expected = DateTime.Now;
var employeeMock = new Mock<Employee>();
employeeMock
.Setup(x => x.getDateOfJoining(It.IsAny<int>()))
.Returns(expected);
var objEmp = employeeMock.Object;
//Act
var actual = objEmp.getDateOfJoining(1);
//Assert
Assert.AreEqual(expected, actual);
}
}
Reference : Moq Quickstart

Moq an object in a static class

I can't get Moq to mock an object that gets created in a static method.
Here is my moq and code
code:
public interface IConfigHelper
{
string GetConfiguration(string sectionName, string elementName);
}
public class ConfigHelper : IConfigHelper
{
public ConfigHelper() { }
public virtual string GetConfiguration(string sectionName, string elementName)
{
string retValue = String.Empty;
//Does things to get configuration and return a value
return retValue;
}
}
public class myRealClass
{
public myRealClass(){}
public string myworkingMethod()
{
var retValue = String.Empty;
retValue = utilSvc.GetConfigurationValue();
return retValue;
}
}
public static class utilSvc
{
public static string GetConfigurationValue()
{
ConfigHelper configUtil = new ConfigHelper(); //NOT BEING MOCKED
return configUtil.GetConfiguration("sectionName/sectionElement", "ClinicalSystem");
}
}
the Test using Moq
[TestFixture(TestName = "Tests")]
public class Tests
{
private Mock<IConfigHelper> configHelperMOCK;
[SetUp]
public void Setup()
{
configHelperMOCK = new Mock<IConfigHelper>();
}
[Test]
public void serviceIsBPManagementForValidSource()
{
//Arrange
string sectionName = "sectionName/sectionElement";
string clinicalElementName = "ClinicalSystem";
string clinicalElementValue = "Zedmed";
configHelperMOCK.Setup(s => s.GetConfiguration(sectionName, clinicalElementName)).Returns(clinicalElementValue);
//act
// the call to myRealClass
//assert
// test assertions
}
}
The issue that I am having is with this line:
ConfigHelper configUtil = new ConfigHelper(); //NOT BEING MOCKED
I cannot get the moq to Mock the object.
I do not want the code to read the config file. I wish to moq away this instance of ConfigHelper
You can't wrap the static class/method but you can redirect it
public static class UtilSvc
{
static UtilSvc()
{
CreatorFunc = () => new ConfigHelper();
}
public static Func<IConfigHelper> CreatorFunc { get; set; }
public static string GetConfigurationValue()
{
var configUtil = CreatorFunc();
return configUtil.GetConfiguration("sectionName/sectionElement",
"ClinicalSystem");
}
}
and then in the test
//...
private Mock<IConfigHelper> configHelperMOCK;
[SetUp]
public void Setup()
{
configHelperMOCK = new Mock<IConfigHelper>();
UtilService.CreatorFunc = () => configHelperMOCK.Object;
}
//...
You cannot mock static class. I would rather propose to inject that IConfigHelper into the myRealClass. That is the usual way how to decouple dependencies and use DI.
public class myRealClass
{
private IConfigHelper _configHelper;
public myRealClass(IConfigHelper configHelper)
{
_configHelper = configHelper;
}
public string myworkingMethod()
{
var retValue = String.Empty;
retValue = _configHelper.GetConfigurationValue();
return retValue;
}
}
Avoid coupling your code to static classes, which in most cases cause you code be to difficult to maintain and test.
Follow the Explicit Dependencies Principle
Methods and classes should explicitly require (typically through
method parameters or constructor parameters) any collaborating objects
they need in order to function correctly.
Give the article a read. It is short and very informative.
If you want to keep the static class then you wrap the static class behind an abstraction.
public interface IUtilSvc {
string GetConfigurationValue();
}
public class utilSvcWrapper : IUtilSvc {
public string GetConfigurationValue() {
return utilSvc.GetConfigurationValue(); //Calling static service
}
}
Or another option is that utlSvc does not have to be static if can be injected into dependent classes
public class utilSvc : IUtilScv {
private readonly IConfigHelper configUtil;
public utilSvc(IConfigHelper configHelper) {
configUtil = configHelper;
}
public string GetConfigurationValue() {
return configUtil.GetConfiguration("sectionName/sectionElement", "ClinicalSystem");
}
}
Inject the IUtilScv into the dependent class so that it is no longer dependent on static class.
public class myRealClass {
private readonly IUtilScv utilSvc;
//Explicit dependency inject via constructor
public myRealClass(IUtilScv utilSvc) {
this.utilSvc = utilSvc;
}
public string myworkingMethod() {
var retValue = utilSvc.GetConfiguration();
return retValue;
}
}
In that case you don't even need IConfigHelper when testing as it has also been abstracted away. And you only need to mock the dependencies needed for the test.
[TestFixture(TestName = "Tests")]
public class Tests {
private Mock<IUtilScv> utilScvMOCK;
[SetUp]
public void Setup() {
utilScvMOCK = new Mock<IUtilScv>();
}
[Test]
public void serviceIsBPManagementForValidSource() {
//Arrange
var expectedClinicalElementValue = "Zedmed";
utilScvMOCK
.Setup(s => s.GetConfiguration())
.Returns(expectedClinicalElementValue)
.Verifiable();
var sut = new myRealClass(utilScvMOCK.Object);
//Act
var actualClinicalElementValue = sut.myworkingMethod();
//Assert
configHelperMOCK.Verify();
Assert.AreEqual(expectedClinicalElementValue, actualClinicalElementValue);
}
}

verifying setup on a passed in mocked object

I am testing my class
public class myclass
{
private IAwesome awesomeObject;
public myclass(IAwesome awesomeObject)
{
this.awesomeObject = awesomeObject;
}
public void MethodUnderTest()
{
this.awesomeObject.RunSomething(); //I want to verify that RunSomething was called
}
}
The way I am doing this is:
//Arrange
var mockAwesome = new Mock<IAwesome>();
mockAwesome.Setup(x=>x.RunSomething()).Returns ... Verify()...;
//Act
var sut = new myclass(mockAwesome.object);
sut.MethodUnderTest();
//Assert
mockAwesome.Verify();
The exception I am getting is:
System.NotSupportedException : Expression references a method that
does not belong to the mocked object: x => x.RunSomething
Is it not possible to test that a specific method was executed on a mocked object that I passed into a class, that is now part of a private member of that class?
Modify set up line to mockAwesome.Setup(x=>x.RunSomething()).Verifiable() and it should work for the example you provided.
[TestClass]
public class MoqVerificationTest {
[TestMethod]
public void Moq_Should_Verify_Setup() {
//Arrange
var mockAwesome = new Mock<IAwesome>();
mockAwesome.Setup(x => x.RunSomething()).Verifiable();
//Act
var sut = new myclass(mockAwesome.Object);
sut.MethodUnderTest();
//Assert
mockAwesome.Verify();
}
public interface IAwesome {
void RunSomething();
}
public class myclass {
private IAwesome awesomeObject;
public myclass(IAwesome awesomeObject) {
this.awesomeObject = awesomeObject;
}
public void MethodUnderTest() {
this.awesomeObject.RunSomething(); //I want to verify that RunSomething was called
}
}
}
To confirm, comment out this.awesomeObject.RunSomething() in your sample class and run the test again. It will fail because you setup the RunSomething as Verifiable() and it was not used.
When testing, works perfectly fine for me...
Try this approach see if anything different results...
void Main()
{
IAwesome awesome = Mock.Of<IAwesome>();
Mock<IAwesome> mock = Mock.Get(awesome);
mock.Setup(m => m.RunSomething());
MyClass myClass = new MyClass(awesome);
myClass.MethodUnderTest();
mock.Verify(m => m.RunSomething(), Times.Once);
}
public interface IAwesome
{
void RunSomething();
}
public class MyClass
{
private IAwesome awesomeObject;
public myclass(IAwesome awesomeObject)
{
this.awesomeObject = awesomeObject;
}
public void MethodUnderTest()
{
this.awesomeObject.RunSomething();
}
}

Categories

Resources