I am testing the functionality of a StoreManager class which has a dependency on DataBaseConfiguration class.
public class StoreManager {
private DataBaseConfiguration dbConfig;
public void Store(string name) {
dbConfig.Store(name);
}
//other methods here
}
The StoreManager class stores to a database and the only way I can test if this method works fine is to query from the database. I have another class in production which does that..
public class QueryManager {
private DataBaseConfiguration dbConfig;
public string Query(QueryExpression expr) {
//query logic
string name = "somename";
return name;
}}
Eventhough I am concerned with testing only my StoreManager class it looks to me like I need to use the QueryManager class to test the storedvalues.
So I have a basic test case like this one...
[TestFixture]
public class StoreManagerTest {
[TestFixtureSetup]
public void Setup() {
DatabaseConfiguration dbConfig = new DatabaseConfiguration(/*test database details*/);
StoreManager sm = new StoreManager(dbConfig);
QueryManager qm = new QueryManager(dbConfig);
}
[Test]
public void TestStore_ValidStore() {
sm.Store("testname");
string queryResult = qm.Query(new QueryExpression("query_expr"));
Assert.AreSame(queryResult, "testname");
}}
As you can see, apart from the ClassUnderTest (which is StoreManager), the QueryManager class also has a dependency on DatabaseConfig.
I don't have a lot of logic inside the StoreManager class, it just delegates to the DataBaseConfig class to store (well actually there are some more classes involved in storing, its not the DataBaseConfig that actually stores the data.. but just for simplicity purpose, lets say so..)
I would like to know if there is a better way to handle this test without involving QueryManager at all?
Also is there a better way to inject the dependency on DataBaseConfiguration into the StoreManager class (considering that the DataBaseConfiguration class takes details about the connection string, etc., of the database to store the data into.. and I would like to pass in a test database rather than the production database connection string there).
To get the dependencies out of the way in testing the most common approach is to either use a handwritten stub or a mocking framework (i.e Moq or RhinoMocks).
Additionally you would have to enable users of the StoreManager class to pass in the DataBaseConfiguration dependency, otherwise you cannot stub it out w/o changing the code. Constructor injection as you do right now is common practice and a clean way to do this (this becomes more convenient if you use an IOC container when you have lots of dependencies), also see here.
If I understand you correctly, you just want to test that the StoreManager actually stores the value you pass to it, you are interested in the behavior of the StoreManager and its interactions with its dependency DataBaseConfiguration - right now you do that by querying the data store itself for verification.
Given that let's go through a bare-bones example using RhinoMocks - the only thing I changed was define the Store method in your DataBaseConfiguration class as virtual so RhinoMocks can override it.
//Arrange
string storeValue = "testname";
var dbConfigMock = MockRepository.GenerateMock<DataBaseConfiguration>();
dbConfigMock.Expect(x => x.Store(storeValue));
StoreManager sm = new StoreManager(dbConfigMock);
//Act
sm.Store(storeValue);
//Assert
dbConfigMock.AssertWasCalled(x => x.Store(storeValue));
This test verifies that the Store method was called on your DataBaseConfiguration class w/o any other dependencies - it tests the behavior of your StoreManager class. This test does not touch the DB nor does it affect any other classes.
Edit:
I'm not sure I understand the concern about using a mocking framework in production code - the mocking framework is only used in your test projects, no reference to it or any code changes are required to the production code itself.
Using a handwritten stub you can do the same assertions "manually": Define a test stub that stores how many times and with what value Store() was called (again this requires the Store method to be declared virtual so it can be overridden):
public class DataBaseConfigurationTest : DataBaseConfiguration
{
public int TimesCalled { get; set; }
public string LastNameStored { get; set; }
public DataBaseConfigurationTest()
{
TimesCalled = 0;
}
public override void Store(string name)
{
TimesCalled++;
LastNameStored = name;
}
}
Now use this test stub in your test instead of the "real" DataBaseConfiguration:
string storeValue = "testname";
DataBaseConfigurationTest dbConfigStub = new DataBaseConfigurationTest();
StoreManager sm = new StoreManager(dbConfigStub);
sm.Store(storeValue);
Assert.AreEqual(1, dbConfigStub.TimesCalled);
Assert.AreEqual(storeValue, dbConfigStub.LastNameStored);
Related
On the xUnit website it says the following about constructor:
xUnit.net creates a new instance of the test class for every test that
is run, so any code which is placed into the constructor of the test
class will be run for every single test. This makes the constructor a
convenient place to put reusable context setup code where you want to
share the code without sharing object instances (meaning, you get a
clean copy of the context object(s) for every test that is run).
I have the following code:
public class ProfilePageTest
{
public ProfilePageTest(Role role)
{
AuthRepository.Login(role)
}
[Theory]
[Roles(Role.Editor, Role.Viewer)]
public void OpenProfilePageTest(Role role)
{
var profile = GetPage<ProfilePage>();
profile.GoTo();
profile.IsAt();
}
}
Is it possible to pass the role from the theory attribute to the constructor, so I don't have to do AuthRepository.Login(role) in every test method that I have.
No, that's not possible. The constructor will be run before anything else, as with any constructor you're used to. I don't see the harm in calling AuthRepository.Login(role) in every test though, because it's a single line of code.
This is quite an excellent blog post about the different ways you can pass data into xUnit tests, but all of them are passing in data to individual methods (tests) rather than in the constructor.
If you are looking to set something up for multiple tests you should have a look int IClassFixture
Quick run down, you setup a class with the shared data:
public class DatabaseFixture : IDisposable
{
public DatabaseFixture()
{
Db = new SqlConnection("MyConnectionString");
// ... initialize data in the test database ...
}
public void Dispose()
{
// ... clean up test data from the database ...
}
public SqlConnection Db { get; private set; }
}
And then in your tests you can "inject" the class (along with the data) into the test class:
public class MyDatabaseTests : IClassFixture<DatabaseFixture>
{
DatabaseFixture fixture;
public MyDatabaseTests(DatabaseFixture fixture)
{
this.fixture = fixture;
}
// ... write tests, using fixture.Db to get access to the SQL Server ...
}
How does one unit test a service which connects to a database?
I have a playerRepository class in data access layer, which interacts with the database directly, and a playerService class in business layer which creates an instance of playerRepository and services random stuff like - deleting player, saving player, getting all players, getting the player by id/name yadda yadda.
I want to unit test the playerService without using the real database, but using in-memory database provided with EF.
The problem is, I'm having trouble figuring out how to set it up.
I have a PlayerContext : DbContext class, which is used as a model to code-first (done this part via tutorial on EF). And I have to add a parameter to constructor DbContextOptionsBuilder<PlayerContext>, but I don't know where to begin. I don't know how and where to setup the connection string, where does the "default" database store itself.
I want to do this by using EF without NSubstitute or Moq, I'm doing this to learn how it's done without using other frameworks except for EF.
public class PlayerContext : DbContext
{
public PlayerContext() : base()
{
}
public DbSet<Player> Players { get; set; }
}
public class Player
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int DciNumber { get; set; }
}
I'm using visual studio provided unit testing
[TestClass]
public class PlayerServiceTest
{
// Should get all the players from database
[TestMethod]
public void GetAllPlayers()
{
// arrange - act
// TODO: Return all the players from the database
// assert
// TODO: Should return empty list
}
And the PlayerService class looks something like this
public class PlayerService
{
private PlayerRepository _playerRepository = new PlayerRepository();
public List<Player> GetAllPlayers()
{
var players = _playerRepository.GetAllPlayers();
return players;
}
PlayerRepository
public class PlayerRepository
{
public List<Player> GetAllPlayers()
{
using (var context = new PlayerContext())
{
var players = context.Players.ToList();
return players;
}
}
Generally my questions are:
How to make the PlayerContext with another connection string which connects to in-memory database in case of unit test, and also how to provide it with the correct connection string when not running via unit-tests
How to change the location of the database, because it's using a default path in C:\Users.
I'm not looking for integration tests with the DAL's PlayerRepository, I just want to test the business layer and all I need is, when I run the tests that the PlayerService to uses the PlayerRepository which connects to in-memory database and that's it. Otherwise it should connect to the local db stored in the same folder as the main exe for the app
Help needed!
The missing piece is dependency injection / IoC. The principle here is to define your dependencies (Repository) with a contract interface that can be mocked out. Inject that dependency into the classes that depend on it. This way you can substitute out concrete implementations like databases, file handling, etc. with mock up objects that return a known state, throw an expected exception, etc. to test your business logic's handling of those scenarios.
public class PlayerService
{
private readonly IPlayerRepository _playerRepository = null;
public PlayerService(IPlayerRepository playerRepository)
{
_playerRepository = playerRepository ?? throw new ArgumentNullException("playerRepository");
}
public List<Player> GetAllPlayers()
{
var players = _playerRepository.GetAllPlayers();
return players;
}
}
Have a look at IoC containers such as Autofac, Unity, Ninject, etc. for examples of how a container can be st up to automatically identify and inject concrete class instances into your services when it constructs them.
When you go to write a unit test you create a mock of the IPlayerRepository class (see: Moq for example) and pass that to your service under test. I.e.:
[Test]
public void TestService()
{
var mockRepository = new Mock<IPlayerRepository>();
mockRepository.Setup(x => x.GetPlayers()).Returns(buildTestPlayerList());
var serviceUnderTest = new PlayerService(mockRepository.Object);
// continue with test...
}
At a worst case: if you want to forgo the container, this can work as well:
public class PlayerService
{
private IPlayerRepository _playerRepository = null;
public IPlayerRepository PlayerRepository
{
get { return _playerRepository ?? (_playerRepository = new PlayerRepository()); }
set { _playerRepository = value; }
}
// ...
}
... and then with the test...
[Test]
public void TestService()
{
var mockRepository = new Mock<IPlayerRepository>();
mockRepository.Setup(x => x.GetPlayers()).Returns(buildTestPlayerList());
var serviceUnderTest = new PlayerService { PlayerRepository = mockRepository.Object };
// continue with test...
}
This is a pattern I call "lazy property injection" where you can opt to send a dependency in, but by default it will simply create the default dependency. This can be a useful pattern when introducing dependency substitution & unit testing into legacy code that was relying heavily on newing up classes mid-code. It's lazy in the sense that the dependency is only "newed" the first time it is accessed. If you call a method in the service that doesn't need the dependency then there is no initialization of every dependency, only the ones that are used. I highly recommend reading up on IoC containers though since they help automate wiring up dependencies.
Hi I am just writting my first unit test and I have a case where I have to test if the correct mapper is returned.
This is my code:
public UserPersonalDetailsDTO GetUserPersonalDetails(int personId)
{
var mapper = ServiceLocator.GetInstance<IMappingService<UserPersonalDetails, UserPersonalDetailsDTO>>();
var userPersonalDetails = UnitOfWork.PersonData.GetUserPersonalDetails(personId);
var userPersonalDetailsDTO = mapper.Map(userPersonalDetails);
return userPersonalDetailsDTO;
}
How would I test if I am getting the correct mapper?
EDIT
I forgot to mention that I am using Unity as my DI Framework this si my constructor:
public ProfileService(IEConnectUow uow, IValidationService validationService, IServiceLocator serviceLocator)
: base(uow, serviceLocator)
{
m_ValidationService = validationService;
}
My CUrrent class inherits from a BaseCLass that have this properties:
protected IEConnectUow UnitOfWork { get; set; }
protected IServiceLocator ServiceLocator { get; set; }
public BaseService(IEConnectUow uow, IServiceLocator serviceLocator)
{
UnitOfWork = uow;
ServiceLocator = serviceLocator;
}
That code is really difficult to unit test. At least two of the dependencies come in via statics (ServiceLocator, UnitOfWork).
I would refactor the code to the following
public class Whatever {
private IMappingService<UserPersonDetails, UserPersonalDetailsDTO> mapper;
private PersonData personData;
public Whatever(IMappingService<UserPersonDetails, UserPersonalDetailsDTO> mapper,
PersonData personData) {}
public UserPersonalDetailsDTO GetUserPersonalDetails(int personId) {
var userPersonalDetails = personData.GetUserPersonalDetails(personId);
var userPersonalDetailsDTO = mapper.Map(userPersonalDetails);
return userPersonalDetailsDTO;
}
}
In the whatever class you can now test the interactions with the objects you pass in. You don't want to be testing that the right mapper is returned in this class. In a unit test, ideally you only want to test the logic of the class and its interactions with dependencies. In this case, I'd simply test the interactions. GetUserPersonalDetails talks to the PersonData object, and uses the Mapper to get the result.
Testing that you get the right mapper isn't the responsibility of this class. Factor that logic out somewhere (perhaps starting with ServiceLocator) into its own class with its own dependencies and verify it does what you want.
Your ServiceLocator is some factory class. If the ServiceLocator is writen by you, you can test is seperately. If it is a libary class, the libary is tested (assumue). You can test is the GetInstance<IMappingService<UserPersonalDetails, UserPersonalDetailsDTO>>(); method is called for the correct types. This can be done with a mocking framework. You make a mock for the GetInstance method and then check if it is called, you know the GetInstance method is right because you have tested it somewhere else.
My test whould look like (pseudo code):
Make mock ServiceLocator.GetInstance
Make mock UnitOfWork.PersonData.GetUserPersonalDetails
Make mock mapper.Map
call GetUserPersonalDetails(int personId)
check if ServiceLocator.GetInstance was correct
I have a repository implemented using LINQ to SQL. I need to do Unit Testing though I don't have a database. How can I write the UT for FreezeAllAccountsForUser method? Can you please show an example using manually mocking?
Note: There is inheritance mapping used in domain objects
Note: Unit Testing is to be done using Visual Studio Team Test
Comment from #StuperUser. Unit testing involves completely isolating code from the other objects it interacts with. This means that if the code fails, you can be sure that the failure is to do with the code under test. To do this you have to fake these objects.
CODE
public void FreezeAllAccountsForUser(int userId)
{
List<DTOLayer.BankAccountDTOForStatus> bankAccountDTOList = new List<DTOLayer.BankAccountDTOForStatus>();
IEnumerable<DBML_Project.BankAccount> accounts = AccountRepository.GetAllAccountsForUser(userId);
foreach (DBML_Project.BankAccount acc in accounts)
{
string typeResult = Convert.ToString(acc.GetType());
string baseValue = Convert.ToString(typeof(DBML_Project.BankAccount));
if (String.Equals(typeResult, baseValue))
{
throw new Exception("Not correct derived type");
}
acc.Freeze();
DTOLayer.BankAccountDTOForStatus presentAccount = new DTOLayer.BankAccountDTOForStatus();
presentAccount.BankAccountID = acc.BankAccountID;
presentAccount.Status = acc.Status;
bankAccountDTOList.Add(presentAccount);
}
IEnumerable<System.Xml.Linq.XElement> el = bankAccountDTOList.Select(x =>
new System.Xml.Linq.XElement("BankAccountDTOForStatus",
new System.Xml.Linq.XElement("BankAccountID", x.BankAccountID),
new System.Xml.Linq.XElement("Status", x.Status)
));
System.Xml.Linq.XElement root = new System.Xml.Linq.XElement("root", el);
//AccountRepository.UpdateBankAccountUsingParseXML_SP(root);
AccountRepository.Update();
}
Repository Layer
namespace RepositoryLayer
{
public interface ILijosBankRepository
{
System.Data.Linq.DataContext Context { get; set; }
List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID);
void Update();
}
public class LijosSimpleBankRepository : ILijosBankRepository
{
public System.Data.Linq.DataContext Context
{
get;
set;
}
public List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID)
{
IQueryable<DBML_Project.BankAccount> queryResultEntities = Context.GetTable<DBML_Project.BankAccount>().Where(p => p.AccountOwnerID == userID);
return queryResultEntities.ToList();
}
public virtual void Update()
{
//Context.SubmitChanges();
}
}
}
Domain Classes
namespace DBML_Project
{
public partial class BankAccount
{
//Define the domain behaviors
public virtual void Freeze()
{
//Do nothing
}
}
public class FixedBankAccount : BankAccount
{
public override void Freeze()
{
this.Status = "FrozenFA";
}
}
public class SavingsBankAccount : BankAccount
{
public override void Freeze()
{
this.Status = "FrozenSB";
}
}
}
Auto generated Class by LINQ to SQL
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.BankAccount")]
[InheritanceMapping(Code = "Fixed", Type = typeof(FixedBankAccount), IsDefault = true)]
[InheritanceMapping(Code = "Savings", Type = typeof(SavingsBankAccount))]
public partial class BankAccount : INotifyPropertyChanging, INotifyPropertyChanged
Simply, you can't. The sole purpose of the repository implementation is talking to the database. So the database technology does matter and you should perform integration tests.
Unit testing this code is impossible because LINQ to Objects is a superset of LINQ to SQL. You might have a green unit test and still get the runtime exception when using real db because you used a feature of LINQ in your repository that cannot be translated into SQL.
The Repository responsibility is to persist domain objects and fetch them on request. i.e. it's job is to take an object and deserialize/serialize it to from some form of durable storage.
So tests for the repository have to test against the real storage in this case a DB. i.e. these are integration tests - tests that your class integrates with the external DB.
Once you have this nailed, the rest of the client/app doesn't have to work against the real DB. They can mock the repository and have fast unit tests. You can assume that GetAccount works since the integration tests pass.
More details:
By passing in the Repository object as a ctor or method arg, you open the doors for passing in a fake or a mock. Thus now the service tests can run without a real repository >> there is no DB-access >> fast tests.
public void FreezeAllAccountsForUser(int userId, ILijosBankRepository accountRepository)
{
// your code as before
}
test ()
{ var mockRepository = new Mock<ILijosBankRepository>();
var service = // create object containing FreezeAllAccounts...
service.FreezeAllAccounts(SOME_USER_ID, mockRepository);
mock.Verify(r => r.GetAllAccountsForUser(SOME_USER_ID);
mock.Verify(r => r.Update());
}
You can by using the IDbSet interface in your datacontext and extracting an interface for your datacontext class. Programming towards interfaces is the key to creating unit testable code.
The reason that you would want to create unit tests for these linq queries is to have a unit test for the logical query. Integration tests are subject to all kinds of false negatives. The db not being in the right state, other queries running at the same time, other integration tests, etc. It is very hard to isolate a db well enough for a reliable integration test. That is why integration tests are so often ignored. If i have to pick one, i want the unit test...
I'm researching NoSQL databases and have a question regarding unit testing. What is the appropriate method to unit test the business logic? How does one mock a NoSQL database?
Your business logic should not touch the database directly, but rather go through a database access layer. This lets you mock that intermediate layer for unit testing. To do this, you can use dependency injection and mocking. There are frameworks that can help you with both of these things, but you can also do it by hand. Here's an example:
Say we have a DAL:
public class DBDataProvider: IDataProvider
{
public string getData()
{
//SQL to get data from actual database.
}
}
As you can see, this implements an interface for something that provides data for your business layer. It might look something like this:
public Interface IDataProvider
{
String getData();
}
Your business layer might look something like this:
public BusinessClass
{
private IDataProvider dataProvider;
public BusinessClass()
{
dataProvider = new DBDataProvider();
}
public BusinessClass(IDataProvider provider)
{
dataProvider = provider;
}
public void doBusinessStuff()
{
dataProvider.getData();
//Do something with data.
}
}
So now in your production code, you will make your business class using the default constructor, which will automatically make your class with a connection to the DB. However, notice that we can create a BusinessClass with an IDataProvider that we specify. So, you can make a "fake" data provider just for testing:
public class MockDataProvider: IDataProvider
{
public string getData()
{
//return some expected result that you can control, without doing a DB call.
}
}
Now in your test, you can create a new MockDataProvider, and pass that into the constructor for BusinessClass. Your business class will now use your mock data provider, instead of the real DB.
Here I did everything by hand, but it gives you an idea of how this works. In real life, you can use mocking and dependency injection frameworks to write a bunch of that code for you.
The same way you mock any dependency. Write a nice, neat contract from which implementation details can be abstracted away, then mock that contract. Typically this is done by using the Data Access Layer as the contract(s).
Without getting into real implementation details, lets say you have a query in your method you want to test: (note, i copied this code from a ravenDB example, but i know 0 about ravenDB, so it might not even compile)
public void SomeMethod()
{
var name = "Hello";
var motto = "World";
using (var docStore = new DocumentStore("localhost", 8080).Initialize())
using (var session = documentStore.OpenSession()){
session.Store(new Company { Name = name, Motto = motto });;
session.SaveChanges();
}
}
That's going to be pretty hard to mock / test because it requires a db on localhost on 8080. Now, if you separate this logic out into another class:
public class AwesomeDAL
public virtual void AddCompany(string name, string motto){
using (var docStore = new DocumentStore("localhost", 8080).Initialize())
using (var session = documentStore.OpenSession()){
session.Store(new Company { Name = name, Motto = motto });;
session.SaveChanges();
}
}
and allow for the injection of the dependency (AwesomeDal):
public class ClassBeingTested
{
public AwesomeDal DAL { get; set; }
public ClassBeingTested() : this(new AwesomeDal()){}
public ClassBeingTested(AwesomeDal dal)
{
this.DAL = dal;
}
public void SomeMethod()
{
var name = "Hello";
var motto = "World";
this.DAL.AddCompany(name, motto);
}
}
And you can now test the BL code in isolation. Or you can simulate database exceptions, or anything else you need to test because your data access layer is abstracted, and its implementation is easily mockable with a framework like Moq or RhinoMocks
In addition to the already posted (correct) answers, let me propose an alternative solution: Use a real development database! Nothing is a more realistic mock that the real thing. If you test on it directly, at least you know that your code will actually run.
If you can abstract away your database easily, I recommend doing that, though.