Maintain context between unit test methods in VS T

2019-06-17 01:23发布

I want to run the following unit tests, in order:

  1. Create new customer with a random number for name, password etc.
  2. Retrieve the just created customer and assert that its properties contain the same random number
  3. Call the ForgotPassword function on same user, with the same random number for user name

As seen clearly, I need to generate a random number once, and share it across 3 test methods.
I cannot seem to find a way to do that.

  • I thought of using the TestContext object, but that gets created for each instance.
  • I tried Using the ClassInitialize() method doesn't help, as it is static, and therefore the number is not accessible by other methods.

Any idea how to achieve my goal?

4条回答
Luminary・发光体
2楼-- · 2019-06-17 01:35

Can you just place your shared data into static variables?

Something simple like this:

    private static string testValue = "something";

    [TestMethod]
    public void TestMethod1()
    {
        Assert.AreEqual(testValue, "something");
        testValue = "something2";
    }

    [TestMethod]
    public void TestMethod2()
    {
        Assert.AreEqual(testValue, "something2");
        testValue = "something3";
    }

    [TestMethod]
    public void TestMethod3()
    {
        Assert.AreEqual(testValue, "something3");
    }

Update: To summarize other comments on this question, I think that everyone is in complete agreement that keeping state between unit tests is a bad idea. My answer was simply a way to do this, if necessary. As I mentioned in another comment, I have had to do this in the past, but not for unit tests. It is sometimes beneficial/necessary to keep state between integration/regression tests where you don't necessarily want to mock objects or isolate parts of the application. As a software tester, you do not always have the influence/ability/permission to immediately refactor or rearchitect an application to be optimal for this testing.

查看更多
我想做一个坏孩纸
3楼-- · 2019-06-17 01:41

It is a really bad idea to be running unit tests that share context. Although I am open to suggestions, I've never come across a good reason for doing what you are suggesting.

If somebody runs your tests in a different order, or in isolation, then they will fail. Tests like this are termed flakey - they pass sometimes, but not others - and it isn't clear why.

It's much better to use a mocking framework like Rhino Mocks to instantiate the mock dependencies in the state that you need. That way, each test is a standalone test that verifies a specific thing without reference to any other tests.

You will find it much easier to maintain tests like these, and there'll be fewer false positives and negatives in your results.

查看更多
我命由我不由天
4楼-- · 2019-06-17 01:43

It is bad form to build unit tests with dependencies. It is not, however, bad form to build functional tests with dependencies. In fact, it's almost required in any application with a normal level of complexity.

What you're trying to do is not a unit test. It's a functional test. And you do need ot share values between test methods to accomplish things from a user's perspective.

查看更多
啃猪蹄的小仙女
5楼-- · 2019-06-17 01:58

What you want to do here is use something like a Repository behind an IRepository interface:

interface IRepository{
    Customer GetCustomer(int id);
}

You can implement a real class in your code that will query a database, but in your tests you can "Mock" this interface to return exactly what you want. Moq is my favorite - and what follows is pseudo code but hopefully you'll get the idea:

[Test]
public void Customer_Should_Have_CreateAt_Set_To_Today{
  var mock = new Mock<IRepository>();
  mock.Setup(x => x.GetCustomer(100)).Returns(new Customer{id = 100, Name = "Steve"});

  var Customer = mock.Object;
  Assert.Equal(Customer.CreatedAt,Date.Today);
}

The idea here is that you control, completely, the data you need to control without relying on when an object is instantiated etc.

查看更多
登录 后发表回答