Show Menu
Cheatography

C# Unit-Tests - Advanced Cheat Sheet by

Implem­ent­ation testing

public void Test() {
  // Arrange
  var mock = new Mock<IActionInterface>();
  var subject = new MySubject(mock.Object);
   
  // Act
  subject.DoSomething();
 
  // Assert
  mock.Verify(e => e.Store(It.IsAny<int>()), Times.Once);
}
- Locks tests with the depend­ency:
 ­ - The test method is aware of IActio­nIn­ter­face.
 ­ - Creates duplicated code.
- Changes to MySubject constr­uctor forces changes throughout all the tests.

Verify vs Callbacks

// If one of these equality comparisons fail we just know that MyAction wasn't called with those arguments.
mock.Verify(e => e.MyAction(
  It.Is<ParameterType>(param =>
    param.Field1 == "some value" &&
    param.Field2 == 3),
  Times.Once);

// Instead:
ParameterType calledArgs = null;
mock
  .Setup(e => e.MyAction(It.IsAny<ParameterType>()))
  .Callback<ParameterType>(param => calledArgs = param);

Assert.That(calledArgs, Is.Not.Null);
Assert.That(calledArgs.Field1, Is.EqualTo("some value"));
Assert.That(calledArgs.Field2, Is.EqualTo(3));
Tip: Avoid stating in your tests how things were done, instead strive to describe what happened. Obse­rvable Behavior

Behavior testing

private int _someVariable;
 
private MySubject MakeSubject()
{
  var mock = new Mock<IActionInterface>();
 
  mock.Setup(e => e.Action(It.IsAny<int>()))
      .Callback<Int>(s => _someVariable= s);
 
  return new MySubject(mock.Object);
}
 
private bool WasStored(int value) =>
  _someVariable == value;
 
[Test]
public void SomeTestMethod()
{
  // Arrange
  var subject = MakeSubject();
 
  // Act
  subject.DoSomething();
 
  // Assert
  Assert.True(WasStored(5));
}
- Changes to depend­encies are done in one place only.
- Focuses on Behavior not implem­ent­ation.

Depend­encies - Common missed tests

What happens when the depend­ency..
throws exception?
returns null?
returns wrong format? (e.g. expected json)
Tip: Testing is about making sure we have answers to questions. Testing is done when we don't have doubts, therefore no more questions.
 

Web Apis

internal abstract class WebApiTests {
  private WebApplicationFactory<Startup> _factory;

  protected WebApiTests() =>
    _factory = new WebApplicationFactory<Startup>();

  protected HttpClient GetClient() =>
    _factory.CreateClient();
}

class MyApiControllerTests : WebApiTests {

  public async Task requestTest() {
    // Arrange
    var client = GetClient();


    // Act
    var response = await client.GetAsync("api/someuri");


    // Assert
    response.EnsureSuccessStatusCode();
    var data = await response.Content.ReadAsAsync<Model>();


    // Assert data ...
  }
}
using Micr­oso­ft.A­sp­Net­Cor­e.M­vc.T­es­ting library for auto mocking out the http layer.

Files

// Hide file access through Stream Factory
public interface IStreamFactory
{
  Stream OpenStream();
  void CloseStream(Stream stream);
}

// On test file
private IStreamFactory MakeStreamStorage()
{
  // Create one isolated MemoryStream per test run!
  _stream = new MemoryStream();
  var mock = new Mock<IStreamFactory>();
  mock.Setup(s => s.OpenStream()).Returns(_stream);
  return mock.Object;
}

Test arrange with files

void Test() {
  // slow & can fail
  var data = File.ReadAllText(@"Data.json");
  // slow & can fail
  var x = JsonConvert.DeserializeObject<MyModel>(data);

  // None of the above lines have anything to do with the test. It's all about Arrange section.
}
Tip: If you feel the need to do this, probably your subject under test is doing to much. See Don't ignore the signs!

Help Us Go Positive!

We offset our carbon usage with Ecologi. Click the link below to help us!

We offset our carbon footprint via Ecologi
 

Comments

No comments yet. Add yours below!

Add a Comment

Your Comment

Please enter your name.

    Please enter your email address

      Please enter your Comment.

          Related Cheat Sheets

          Regular Expressions Cheat Sheet
          Python Cheat Sheet

          More Cheat Sheets by AlienEngineer