Telerik blogs
DotNetT2 Light_1200x303

According to StackOverflow, C# is one of the most-loved programming languages. And I completely understand that—it is powerful, easy to learn and consistently improving and developing. It is a living language. :)

The last couple of years, there were new features added to the languages, and the new versions keep coming up—C# 7, C# 8, C# 9.

As you know, we at Progress Telerik are proud that our products are always in sync with the latest things in the .NET world, and C# 9 and JustMock are no exception.

Most of the new features are easy to use in unit tests and in mocking, but there are some interesting things that I would like to show you so you can easily use the C# features in the unit testing:

  • Static local functions (C# 8)
  • Async methods
  • Records
  • Init
  • Pattern Matching

To illustrate these, we will use a class Foo.

public class Foo
{
    public Foo()
    {
        this.Bar = 10;
        this.DateTime = new DateTime(2021, 1, 1);
    }
 
    public int Bar { get; init; }
    public DateTime DateTime { get; init; }
 
    public bool IsInRange(int i) =>
        i is (>= 1 and <= 10) or (>= 100 and <= 200);
}
 
public record Person
{
    public string LastName { get; }
    public string FirstName { get; }
 
    public Person(string first, string last) => (FirstName, LastName) = (first, last);
}
 
public record Teacher : Person
{
    public string Subject { get; }
 
    public Teacher(string first, string last, string sub)
        : base(first, last) => Subject = sub;
}

Note: To run the examples, you need to download and install JM from here.

1. Let’s First Mock the Static Functions Using Mock.Local

[TestMethod]
public void TestStaticLocal()
{
    // Arrange
    var sut = new Foo();
     
    // Here is how to mock the static function
    Mock.Local.Function.Arrange<int>(sut, "MethodWithStaticLocal", "Add", Arg.Expr.AnyInt, Arg.Expr.AnyInt).Returns(1);
  
    // Act
    var result = sut.MethodWithStaticLocal();
  
    // Assert
    Mock.Assert(sut);
    Assert.AreNotEqual(12, result);
}

2. Async Streams

Starting with C# 8.0, you can create and consume streams asynchronously. A method that returns an asynchronous stream has three specifics:

  • It’s declared with the async modifier
  • It returns an IAsyncEnumerable<T>
  • The method contains yield return statements to return successive elements in the asynchronous stream

In the example below, you can see an example of such a method along with an example of how you could mock it:

[TestMethod]
public async Task TestAsyncEnumFromArray()
{
    // Arrange
    var expected = new int[] { 10, 20, 30 };
 
    Mock.Arrange(() => Foo.GetAsyncCollection())
        .Returns(expected.GetEnumerator().ToAsyncEnumerable<int>());
 
    // Act
    var result = Foo.GetAsyncCollection();
 
    // Assert
    Mock.Assert<Foo>();
    int index = 0;
    await foreach (var number in result)
    {
        Assert.AreEqual(expected[index++], number);
    }
}

3. Init Only Setters

Init only setters provide consistent syntax to initialize members of an object. Property initializers make it clear which value is setting which property. The downside is that those properties must be settable. Starting with C# 9.0, you can create init accessors instead of set accessors for properties and indexers.

How do you mock it when you write a test? Using Mock.NonPublic.ArrangeSet method of JustMock.

[TestMethod]
public void TestInit()
{
    // Arrange 
    var fooMock = Mock.Create<Foo>();
    bool properyInitCalled = false;
 
    Mock.NonPublic.ArrangeSet(fooMock, "Bar", 10)
        .IgnoreInstance()
        .DoInstead(() => properyInitCalled = true);
 
    // Act 
    var foo = new Foo();
 
    // Assert
    Assert.IsTrue(properyInitCalled);
}

or

[TestMethod]
public void TestInit2()
{
    // Arrange
    var fooMock = Mock.Create<Foo>(Constructor.NotMocked);
    dynamic fooMockWrapper = Mock.NonPublic.Wrap(fooMock);
 
    Mock.NonPublic.Arrange(fooMockWrapper.Bar = 10)
        .IgnoreInstance()
        .MustBeCalled();
     
    // Act
    var foo = new Foo();
 
    // Assert
    Mock.NonPublic.Assert(fooMockWrapper.Bar = 10, Occurs.Once());
}

4. Pattern Matching

Another great addition to the C# language is Pattern Matching. I won’t explain now what this is as here you can learn more about it. But I’ll say this is really something that gives C# devs more creativity and flexibility!

 

As the docs say, basically, you look at a given structure and, based on the way it looks, you identify it and you then can immediately use it. If you get a bag of fruit, you look down and immediately see the difference between the apples and the pears.

To show you how such functionality can be mocked with the InRange method, this is our sample of pattern matching and then the test below:

public bool IsInRange(int i) =>
    i is (>= 1 and <= 10) or (>= 100 and <= 200);
 
...
 
[TestMethod]
public void Mock_PatternMatchingTest()
{
    // Arrange
    var foo = Mock.Create<Foo>(Behavior.CallOriginal);
    Mock.Arrange(() => foo.IsInRange(Arg.AnyInt)).Returns(true);
 
    // Act
    var result20 = foo.IsInRange(20);
    var result150 = foo.IsInRange(150);
 
    //Assert
    Assert.AreEqual(true, result20);
    Assert.AreEqual(true, result150);
}

I know that reading code is not the same as running it, so to use it and play with the samples, follow the steps below:

  • Download JustMock for free
  • Install it
  • Download the project from here
  • Play! :)

For more tricks and trips on how to use the API of JustMock to write tests fast, read our Cheat Sheet.

Try It Out

If you are intrigued (hopefully you are 🤞), I’d be more than happy to hear your honest feedback in the comments.

Whether you:

  • Are new to Telerik JustMock—learn more about it via the product page. It comes with a 30-day free trial, giving you some time to explore the capabilities of JustMock.
  • Want to take advantage of Mihail Vladov’s advice on writing user tests—download the Unit Testing eBook now.

Regardless of the above “cases,” don’t be shy to:

Try The Latest JustMock Now

You won’t regret it.


Rossitza-Fakalieva
About the Author

Rossitza Fakalieva

Rossitza Fakalieva is a Technical Manager, Microsoft MVP in Developer Technologies and a Director of the Bulgarian chapter of the global Women Who Code organization. She previously worked on the Telerik engineering team and defines herself as .NET enthusiast. She loves to empower others to grow in their career and in the tech field—by teaching, by delivering courses and presentations, and as part of her daily job.

Related Posts

Comments

Comments are disabled in preview mode.