user1664857
user1664857

Reputation: 23

How to pass values across test cases in NUnit 2.6.2?

I am having two Methods in Unit Test case where First Insert Records into Database and Second retrieves back data. I want that input parameter for retrieve data should be the id generated into first method.

private int savedrecordid =0;
private object[] SavedRecordId{ get { return new object[] { new object[] { savedrecordid  } }; } }


[Test]
public void InsertInfo()
{
    Info oInfo = new Info();
    oInfo.Desc ="Some Description here !!!";
    savedrecordid  = InsertInfoToDb(oInfo);
}

[Test]
[TestCaseSource("SavedRecordId")]
public void GetInfo(int savedId)
{
    Info oInfo  = GetInfoFromDb(savedId);
}

I know each test case executed separately and separate instance we can't share variables across test methods.

Please let me know if there is way to share parameters across the test cases.

Upvotes: 1

Views: 1932

Answers (1)

Akim
Akim

Reputation: 8699

The situation you describe is one of unit tests' antipatterns: unit tests should be independent and should not depend on the sequence in which they run. You can find more at the xUnit Patterns web site:

And both your unit tests have no asserts, so they can't prove whether they are passing or not.

Also they are depend on a database, i.e. external resource, and thus they are not unit but integration tests.

So my advice is to rewrite them:

  • Use mock object to decouple from database
  • InsertInfo should insert info and verify using the mock that an appropriate insert call with arguments has been performed
  • GetInfo should operate with a mock that returns a fake record and verify that it works fine

Example

Notes: * I have to separate B/L from database operations… * … and make some assumptions about your solution

// Repository incapsulates work with Database
public abstract class Repository<T>
    where T : class
{
    public abstract void Save(T entity);
    public abstract IEnumerable<T> GetAll();
}

// Class under Test
public class SomeRule
{
    private readonly Repository<Info> repository;

    public SomeRule(Repository<Info> repository)
    {
        this.repository = repository;
    }

    public int InsertInfoToDb(Info oInfo)
    {
        repository.Save(oInfo);

        return oInfo.Id;
    }

    public Info GetInfoFromDb(int id)
    {
        return repository.GetAll().Single(info => info.Id == id);
    }
}

// Actual unittests
[Test]
public void SomeRule_InsertInfo_WasInserted() // ex. InsertInfo
{
    // Arrange
    Info oInfo = new Info();
    oInfo.Desc = "Some Description here !!!";

    var repositoryMock = MockRepository.GenerateStrictMock<Repository<Info>>();

    repositoryMock.Expect(m => m.Save(Arg<Info>.Is.NotNull));

    // Act
    var savedrecordid  = new SomeRule(repositoryMock).InsertInfoToDb(oInfo);

    // Assert
    repositoryMock.VerifyAllExpectations();
}

[Test]
public void SomeRule_GetInfo_ReciveCorrectInfo() // ex. GetInfo
{
    // Arrange
    var expectedId = 1;
    var expectedInfo = new Info { Id = expectedId, Desc = "Something" };

    var repositoryMock = MockRepository.GenerateStrictMock<Repository<Info>>();

    repositoryMock.Expect(m => m.GetAll()).Return(new [] { expectedInfo }.AsEnumerable());

    // Act 
    Info receivedInfo  = new SomeRule(repositoryMock).GetInfoFromDb(expectedId);

    // Assert
    repositoryMock.VerifyAllExpectations();

    Assert.That(receivedInfo, Is.Not.Null.And.SameAs(expectedInfo));
}

ps: full example availabel here

Upvotes: 5

Related Questions