单元测试 - 我应该如何测试这种设计? [英] Unit Testing - How should I test this kind of design?

查看:20
本文介绍了单元测试 - 我应该如何测试这种设计?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我们的设计有两层:API 和操作.

In my application there are 2 layers in our design: APIs and Operations.

1.操作实现代码的真实"逻辑,例如:对用户进行身份验证、检索图书信息、通知用户他的图书已被查看.

1.Operations implement the "real" logic of code, for example: Authenticating the user, Retrieving book information, Informing a user that his book has been viewed.

许多 API 可能会使用相同的操作.

The same operation may be used by many APIs.

2.API由用户执行:他们接收参数,然后根据API的逻辑执行各种操作.

2.APIs are executed by users: they receive parameters, and then execute various operations according to the logic of the API.

例如:ViewBookAPI:

For example: ViewBookAPI:

class BookApis
{
/**
    * authenticateUserOperation, retreiveBookOperation, informUserBookViewOperation
    * are injected to this class. (Dependency Injection)
*/  
public function viewBookApi($bookId, $accessToken)
{
    $internalUserId = $this->authenticateUserOperation($accessToken);

    $book = $this->retrieveBookOperation($bookId, $internalUserId);

    $this->informUserBookWasViewedOperation($book->getOwnerUserId(), $bookId);

        return $book->getContent();
    }
}

<小时>

我应该如何测试这个设计?


How should I test this design?

1.如果我测试 API,那么我必须对使用相同操作的 API 重复相同的测试.

1.If I test the APIs, then I'll have to repeat the same tests for APIs which are using the same operations.

2.如果我测试操作,我所要做的就是验证 API 是否正确使用了操作.

2.If I test the operations, all I have to do is to verify that an API is using the operations correctly.

但是如果错误的对象被注入到 API 中怎么办?没有任何测试会失败.

But what if a wrong object is injected to an API? No test would fail then.

非常感谢.

推荐答案

你的设计很常见(理所当然),所以我有点惊讶这个问题不断出现.

Your design is quite common (and rightfully so), so I'm a bit surprised that this question keeps coming up.

您需要在这里进行两种类型的测试:

There are two types of tests you need here:

  1. 集成测试 - 确保从 API 调用开始到操作层完成其工作结束的流程正常工作
  2. 单元测试 - 测试 API 层和操作层的每个类
  1. Integration tests - make sure that the flow that starts with the API call and ends with the Operations layer doing its job, is working correctly
  2. Unit tests - test each of the classes of the API layer, as well as of the Operations layer

集成测试是不言自明的(如果没有,请告诉我,我会详细说明),所以我猜你指的是单元测试.两个不同的层需要进行不同的测试.

Integration tests are pretty self explanatory (if not, let me know and I'll elaborate), so I'm guessing that you're referring to unit tests. The two different layers need to be tested differently.

运营层:

在这里,您要检查执行实际工作的类是否正常工作.这意味着您应该实例化您正在测试的类,为其提供输入,并检查它提供的输出是否符合您的期望.

Here you're trying to check that the classes doing the actual job are working. This means that you should instantiate the class you're testing, feed it with input, and check that the output it provides matches your expectations.

假设你有一个这样的类:

Say you have a class of this sort:

public class OperationA {
    public int multiply(int x, int y) {
        return x * y;
    }
}

检查它是否符合您的预期意味着编写一个测试,例如(测试用例本身只是一个例子,不要太当真):

Checking that it does what you expect would mean writing a test such as (the test cases themselves are just an example, do not take too seriously):

public class OperationATest {
    @Test
    public void testMultiplyZeroByAnyNumberResultsInZero() {
        OperationA op = new OperationA();

        assertEquals(0, op.multiply(0, 0));
        assertEquals(0, op.multiply(10, 0));
        assertEquals(0, op.multiply(-10, 0));
        ...
    }

    @Test
    public void testMultiplyNegativeByNegativeResultsInPositive() {
        ...
    }

    ...
}

API 层:

在这里,您尝试检查类是否使用操作层中的正确类,以正确的顺序执行正确的操作.为此,您应该使用模拟,并使用模拟的 verify 操作.

Here you're trying to check that the classes are using the right classes from the Operations layer, in the right order, doing the right operations. In order to do that, you should use mocks, and use the verify operations of mocks.

假设你有一个这样的类:

Say you have a class of this sort:

public class API_A {

    private OperationA op;

    public API_A(OperationA op) {
        this.op = op;
    }

    public int multiplyTwice(int a, int b, int c) {
        int x = op.multiply(a, b);
        int y = op.multiply(x, c);

        return y;
    }
}

检查它是否符合您的预期意味着(使用 Mockito 语法)编写测试,例如:

Checking that it does what you expect would mean (using Mockito syntax) writing a test such as:

public class API_A_Test {
    @Test
    public void testMultiplyTwiceMultipliesTheFirstNumberByTheSecondAndThenByTheThird() {
        OperationA op = mock(OperationA.class); 
        when(op.multiply(12, -5)).thenReturn(60);
        API_A api = new API_A(op);

        api.multiply(12, -5, 0);

        verify(op).multiply(12, -5);
        verify(op).multiply(-60, 0);
    }

}

这篇关于单元测试 - 我应该如何测试这种设计?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆