I have a class that I would like to test with Unit tests. It has some logic to look for some values in the local xml file, and if the value is not found it will read some external source (SqlServer DB). But during Unit testing I don't want this component to interact with Sql Server at all. During unit testing I would like to replace SqlServer implementation of the External source reader to some Noop reader. What is the good approach to achieve that? Important note: I can't define constructor that accepts instance of reader type since it is client facing API and I want to limit what they can do with my classes. I am currently using few ways in Unit tests:
- Use reflection to set value of the private/protected property to my mocked implementation of the reader
- Define factory that will create concrete class. Register factory in Unity container & class under test will get factory object from DI container and instantiate reader according to my needs
- Subclass class-under-test and set property there.
But none of them seem to be clean enough to me. Are there any better ways to achieve that? Here is the sample code to demonstrate example of the class-under-the-test:
namespace UnitTestProject1
{
using System.Collections.Generic;
using System.Data.SqlClient;
public class SomeDataReader
{
private Dictionary<string, string> store = new Dictionary<string, string>();
// I need to override what this property does
private readonly IExternalStoreReader ExternalStore = new SqlExternalStoreReader(null, false, new List<string>() {"blah"});
public string Read(string arg1, int arg2, bool arg3)
{
if (!store.ContainsKey(arg1))
{
return ExternalStore.ReadSource().ToString();
}
return null;
}
}
internal interface IExternalStoreReader
{
object ReadSource();
}
// This
internal class SqlExternalStoreReader : IExternalStoreReader
{
public SqlExternalStoreReader(object arg1, bool arg2, List<string> arg3)
{
}
public object ReadSource()
{
using (var db = new SqlConnection("."))
{
return new object();
}
}
}
internal class NoOpExternalStoreReader : IExternalStoreReader
{
public object ReadSource()
{
return null;
}
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var objectToTest = new SomeDataReader();
objectToTest.Read("", -5, false); // This will try to read DB, I don't want that.
}
}
Aucun commentaire:
Enregistrer un commentaire