You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Mock在C#中对IEnumerable接口进行TDD测试?附FizzBuzz代码片段

Alright, let's break this down step by step. I’ll walk you through how to use a mocking framework (Moq, the go-to for C#) to practice Test-Driven Development (TDD) with IEnumerable interfaces, then apply that directly to your FizzBuzz-focused BusinessHandler code.

TDD with Mocking IEnumerable in C#

First, let's align on basics: TDD follows the Red-Green-Refactor cycle—write a failing test first, write just enough production code to make it pass, then clean up both test and production code. For IEnumerable dependencies, we’ll mock individual rule implementations and pass them as a collection to our BusinessHandler.

1. Setup Your Test Environment

First, add the Moq package to your test project via NuGet:

  • Using Package Manager Console: Install-Package Moq
  • Using .NET CLI: dotnet add package Moq

You’ll also need a testing framework like Xunit or NUnit (I’ll use Xunit for examples here).

2. Define the Missing Interface & Complete Production Code

Your snippet references IBusinessRule, so let's define that first, then finish the GetResult method (since it was incomplete):

IBusinessRule Interface

public interface IBusinessRule
{
    // Returns a replacement string if the rule applies, null otherwise
    string Apply(int number);
}

Completed BusinessHandler

public class BusinessHandler : IBusinessHandler 
{ 
    private readonly IEnumerable<IBusinessRule> _businessRules; 

    public BusinessHandler(IEnumerable<IBusinessRule> businessRules) 
    { 
        _businessRules = businessRules; 
    } 

    public IEnumerable<string> GetResult(int inputValue) 
    { 
        var outputList = new List<string>(); 
        for (int element = 1; element <= inputValue; element++) 
        { 
            string tempOutput = element.ToString(); 
            // Apply all rules to the current number
            foreach (var rule in _businessRules) 
            { 
                var ruleResult = rule.Apply(element);
                if (!string.IsNullOrEmpty(ruleResult))
                {
                    tempOutput = ruleResult;
                }
            }
            outputList.Add(tempOutput); 
        } 
        return outputList; 
    } 
}

// Don't forget the IBusinessHandler interface
public interface IBusinessHandler
{
    IEnumerable<string> GetResult(int inputValue);
}

3. Test Cases for FizzBuzz Behavior

Now let’s write tests using Moq to mock our IBusinessRule implementations and validate the handler’s behavior.

Test 1: No Rules → Returns Raw Numbers

This tests the base case where no rules are applied—we should get back string representations of the input range.

[Fact]
public void GetResult_WithNoRules_ReturnsRawNumberStrings()
{
    // Arrange
    var emptyRules = new List<IBusinessRule>();
    var handler = new BusinessHandler(emptyRules);
    const int input = 3;

    // Act
    var result = handler.GetResult(input).ToList();

    // Assert
    Assert.Equal(new List<string> { "1", "2", "3" }, result);
}

Test 2: Fizz Rule Only → Replaces Multiples of 3

Mock a rule that triggers for multiples of 3 and returns "Fizz".

[Fact]
public void GetResult_WithFizzRule_ReplacesMultiplesOf3WithFizz()
{
    // Arrange
    var fizzRuleMock = new Mock<IBusinessRule>();
    // Setup: return "Fizz" for multiples of 3, null otherwise
    fizzRuleMock.Setup(r => r.Apply(It.Is<int>(n => n % 3 == 0)))
                .Returns("Fizz");
    fizzRuleMock.Setup(r => r.Apply(It.Is<int>(n => n % 3 != 0)))
                .Returns(null);

    var rules = new List<IBusinessRule> { fizzRuleMock.Object };
    var handler = new BusinessHandler(rules);
    const int input = 4;

    // Act
    var result = handler.GetResult(input).ToList();

    // Assert
    Assert.Equal(new List<string> { "1", "2", "Fizz", "4" }, result);
}

Test 3: Fizz + Buzz Rules → FizzBuzz for Multiples of 15

Combine two rules to test the classic FizzBuzz behavior.

[Fact]
public void GetResult_WithFizzAndBuzzRules_ReplacesMultiplesOf15WithFizzBuzz()
{
    // Arrange
    // Fizz rule setup
    var fizzRuleMock = new Mock<IBusinessRule>();
    fizzRuleMock.Setup(r => r.Apply(It.Is<int>(n => n % 3 == 0)))
                .Returns("Fizz");
    fizzRuleMock.Setup(r => r.Apply(It.Is<int>(n => n % 3 != 0)))
                .Returns(null);

    // Buzz rule setup
    var buzzRuleMock = new Mock<IBusinessRule>();
    buzzRuleMock.Setup(r => r.Apply(It.Is<int>(n => n % 5 == 0)))
                .Returns("Buzz");
    buzzRuleMock.Setup(r => r.Apply(It.Is<int>(n => n % 5 != 0)))
                .Returns(null);

    var rules = new List<IBusinessRule> { fizzRuleMock.Object, buzzRuleMock.Object };
    var handler = new BusinessHandler(rules);
    const int input = 15;

    // Act
    var result = handler.GetResult(input).ToList();

    // Assert
    Assert.Equal("Fizz", result[2]); // Index 2 = number 3
    Assert.Equal("Buzz", result[4]); // Index 4 = number 5
    Assert.Equal("FizzBuzz", result[14]); // Index 14 = number 15
}

Test 4: Input = 0 → Returns Empty List

Validate edge case where input is zero (no numbers to process).

[Fact]
public void GetResult_WithInput0_ReturnsEmptyList()
{
    // Arrange
    var mockRules = new List<IBusinessRule>();
    var handler = new BusinessHandler(mockRules);

    // Act
    var result = handler.GetResult(0).ToList();

    // Assert
    Assert.Empty(result);
}

4. Key Mocking Tips for IEnumerable

  • Mock Individual Elements: For most cases, you don’t need to mock the IEnumerable itself—just create a list of mocked IBusinessRule instances and pass it to the handler. This keeps tests simple and focused.
  • Verify Rule Execution (Optional): If you want to ensure rules are being called correctly, add verification steps:
    // Verify Fizz rule was called once for number 3
    fizzRuleMock.Verify(r => r.Apply(3), Times.Once);
    
  • Use It.Is<T> for Conditional Setup: This lets you define exactly when a rule should trigger, which is perfect for FizzBuzz’s divisibility checks.

内容的提问来源于stack exchange,提问作者user1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:21:40