Unit Test for n tier architecture

2019-07-19 04:46发布

I am using 3 tier architecture: Controller, Business, and Data Layer. In my Data Layer, I am making a call to an Sql Server Database by passing Connection String and other necessary parameters.

I have to write unit tests for the Controller layer and Business layer. I want to write a stub (fake repository) from which I would return the hard coded values/result. When I write a test for business layer, the logic should call this stub instead of the real database.

How can I write the code in the business layer to achieve this?

Business Layer:

public string GetValues(string xmlData)
{
    DataObject do = new DataObject ();
    string result = do.GetValues(xmlData);
    return result;
}

Data access:

public static string GetValues(string xmlData)
{
    return SqlHelper.ExecuteScalar(
        ConfigurationManager.AppSettings["ConnectionString"].ToString(),     
        "DBO.usp_GetDetail",
        xmlData
    ).ToString();
}

1条回答
冷血范
2楼-- · 2019-07-19 05:21

In order to test you scenario, your code has to be testable. If it follows SOLID principles it most likely is. But let's focus on what is essential to do this kind of unit testing:

  1. Your business layer should depend on abstraction (this in most of the time means interfaces) instead of concrete classes. This way, in unit test you can provide stubs for those dependencies.
  2. Business layer's dependencies should be provided via dependency injection (for example constructor injection), so that in unit tests you can easily pass them stubbed objects.

Same principles should apply to Controller - Business Layer interaction. When you stick to those two rules (which essentially narrows to SOLID's dependency inversion principle), your code will be much more unit testable than otherwise (sticking to SOLID principles is overall good idea).

Since you'll probably end up writing mocks/stubs, I suggest using existing mocking framework, like Moq or FakeItEasy.

Edit - if code is that tighly coupled, your options are limited to:

  • refactoring (this is obvious, but with legacy system might not be possible/worth the effort)
  • use paid tool, like TypeMock Isolator. Isolator uses compiler API to intercept method calls and as a result can stub/mock calls to static methods, private members and all the stuff that free frameworks don't let you.
  • use Microsoft Moles. Moles generate fake types utilizing dynamic assembly generation. This gives you Isolator-like flexibility, but is free. Note that it's a bit heavier framework (extra assembiles, files etc).
查看更多
登录 后发表回答