如何在 salesforce 中进行单元测试?

发布于 2024-10-06 00:53:09 字数 2198 浏览 12 评论 0 原文

我已经在 salesforce 上编写了代码,为了发布单元测试必须覆盖至少 75%

我面临的是,从 classTwo 调用方法的 classOne 也必须覆盖 classOne 内 classTwo 的单元测试 em> 即使它已经在 classTwo 文件中完成了。

File MyClassTwo

 public with sharing class ClassTwo {

    public String method1() {
        return 'one';
    }

    public String method2() {
        return 'two';
    }

    public static testMethod void testMethod1() {

        ClassTwo two = new ClassTwo();
        String out = two.method1();
        system.assertEquals(out, 'one'); //valid    
    }

    public static testMethod void testMethod2() {
        ClassTwo two = new ClassTwo();
        String out = two.method2();
        system.assertEquals(out, 'two'); // valid
    }

}

File MyClassOne

 public with sharing class ClassOne {

    public String callClassTwo() {
        ClassTwo foo = new ClassTwo();
        String something = foo.method1();

        return something;
    }

    public static testMethod void testCallClassTwo() {
        ClassOne one = new ClassOne();
        String out = one.callClassTwo();

        system.assertEquals(out, 'one');
    }
}

测试 MyClassOne 的结果不会返回 100% 测试覆盖率,因为它说我没有覆盖 MyClassOne 文件内的 MyClassTwo method2() 部分。

但我已经在 MyClassTwo 文件中为 MyClassTwo 编写了单元测试,如您所见。

那么这是否意味着我必须将 MyClassTwo 文件中的单元测试复制并粘贴到 MyClassOne 中?

这样做可以让我得到 100% 的覆盖率,但这看起来真的很烦人和荒谬。 ClassA和ClassB有相同的测试吗...?我做错了吗还是这就是方法?

话虽如此,是否可以在 salesforce 中创建模拟对象?我还没有弄清楚如何......

http://sites.force.com /answers/ideaView?c=09a30000000D9xt&id=087300000007m3fAAA&returnUrl=/apex/ideaList%3Fc%3D09a30000000D9xt%26category%3DApex%2B%2526%2BVisualforce%26p%3D19%26sort%3 D热门

UDPATE< /strong>

我重新编写了代码并在上面进行了更新,这次可以肯定 classOne 测试不会返回 100%,即使它没有调用 classTwo method2()

I've done writing code on salesforce and in order to release the unit tests have to cover at least 75%.

What I am facing is that the classOne that calls methods from classTwo also have to cover classTwo's unit test within classOne even though it is done in classTwo file already.

File MyClassTwo

 public with sharing class ClassTwo {

    public String method1() {
        return 'one';
    }

    public String method2() {
        return 'two';
    }

    public static testMethod void testMethod1() {

        ClassTwo two = new ClassTwo();
        String out = two.method1();
        system.assertEquals(out, 'one'); //valid    
    }

    public static testMethod void testMethod2() {
        ClassTwo two = new ClassTwo();
        String out = two.method2();
        system.assertEquals(out, 'two'); // valid
    }

}

File MyClassOne

 public with sharing class ClassOne {

    public String callClassTwo() {
        ClassTwo foo = new ClassTwo();
        String something = foo.method1();

        return something;
    }

    public static testMethod void testCallClassTwo() {
        ClassOne one = new ClassOne();
        String out = one.callClassTwo();

        system.assertEquals(out, 'one');
    }
}

The result of testing MyClassOne would not return 100% test coverage because it says I have not covered MyClassTwo method2() part inside of MyClassOne file.

But I already wrote unit test for MyClassTwo inside of MyClassTwo file as you can see.

So does this mean I have to copy and paste the unit test in MyClassTwo file over to MyClassOne?

Doing so gives me 100% coverage but this seems really annoying and rediculous. Having same test in ClassA and ClassB....? Am I doing wrong or is this the way?

Having said, is it possible to create mock object in salesforce? I haven't figure how yet..

http://sites.force.com/answers/ideaView?c=09a30000000D9xt&id=087300000007m3fAAA&returnUrl=/apex/ideaList%3Fc%3D09a30000000D9xt%26category%3DApex%2B%2526%2BVisualforce%26p%3D19%26sort%3Dpopular

UDPATE

I re-wrote the code and updated above, this time for sure classOne test would not return 100% even though it is not calling classTwo method2()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

上课铃就是安魂曲 2024-10-13 00:53:09

关于 Java 模拟库的评论在 Salesforce 世界中没有多大帮助;)在我的项目中,我们通常旨在在测试方法中制作自己的测试数据,调用实际功能,检查结果......Salesforce 端的整个测试框架是负责事务回滚(所以无论测试失败还是通过,最终都不会将测试数据保存到DB中)。

不管怎样...

Masato,你的类无法编译(类范围之外的方法,public String hello(),没有返回任何字符串)...修复后,我只需右键单击 MyClassA -> ; Force.com->运行测试并获得完整的代码覆盖率,没有任何问题,因此您的问题一定出在其他地方...

如下所示: http://dl.dropbox.com/u/709568/stackoverflow/masato_code_coverage.png

我正在尝试思考可能出了什么问题......你确定所有类都编译并且保存在服务器端?您是否将测试方法放在与功能相同的类中或单独的类中(通常我使用类似的名称创建单独的类名,例如 MyClassATest)。如果它是一个单独的类 - 您在哪个文件上单击“运行测试”?
最后但并非最不重要的 - 如果您在从沙箱部署到生产期间遇到此问题,请确保在部署向导中选择了所需的所有类?

Comments about Java mock libraries aren't very helpful in Salesforce world ;) At my projects we usually aimed for making our own test data in the test method, calling real functionality, checking the results... and whole test framework on Salesforce side is responsible for transaction rollback (so no test data is saved to DB in the end regardless whether the test failed or passed).

Anyway...

Masato, your classes do not compile (methods outside class scope, public String hello() without any String returned)... After I fixed it I simply right-clicked the MyClassA -> Force.com -> run tests and got full code coverage without any problems so your issue must lie somewhere else...

Here's how it looks: http://dl.dropbox.com/u/709568/stackoverflow/masato_code_coverage.png

I'm trying to think what might have gone wrong... are you sure all classes compile and were saved on server side? Did you put test methods in same classes as functionality or in separate ones (generally I make separate class name with similar name like MyClassATest). If it's a separate class - on which file did you click "run tests"?
Last but not least - if you're facing this issue during deployment from sandbox to production, make sure you selected all classes you need in the deployment wizard?

丑疤怪 2024-10-13 00:53:09

如果您确实想要进行“单元”测试,则应该测试 B 类的行为和 A 类的行为,模拟对 B 类方法的调用。

这是模仿爱好者和其他人之间的艰难对话(我认为马丁·福勒不是一个“嘲笑者”)。

反正。您不应该再考虑 100% 的覆盖率。你应该思考:

  • 我为什么要测试?

  • 我如何测试?

在这里,我肯定会进行 2 个测试:

  • 将 B 类测试放入 b 类测试文件中,以确保 B 方法得到很好的实现,以及所有副作用、副作用等。

  • 对模拟 B 类的 A 类进行一项测试

什么是模拟?

保持非常简单:模拟是测试中代码的一部分,它会说:当调用 B 类方法时,始终返回此值:“+++”。

通过这样做,您可以拥有一个可维护和可模块化的测试套件。

在java中,我喜欢mockito: http://mockito.org/

虽然我的一位同事是easymock的首席维护者: http://easymock.org/

希望这会有所帮助。询问我是否需要进一步帮助。

编辑一些示例

使用Java和mockito:

public class aUTest {

    protected A a;

    @Mock protected B b;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        a = new A();
        ReflectionTestUtils.setField(a, "b", b);
    }

        @Test
    public void test_A_method_should_not_throw_exception()
            when(b. execute()).thenReturn(true); //just an example of a return value from b. execute()
            Boolean result = a.testHello();

        // Assert
        Assert.assertEquals(true, result);
    }

If you really want to "unit" test, you should test the behavior of your class B AND the behavior of your class A, mocking the call to the class B method.

That's a tough conversation between mock lovers and others (Martin Fowler I think is not a "mocker").

Anyway. You should stop thinking about 100% coverage. You should think about:

  • Why am i testing?

  • How am i testing?

Here, i'd definitely go for 2 tests:

  • One test for the B class into the b class test file to be sure the B method is well implemented, with all the side effects, side values etc.

  • one test for the A class mocking the class B

What is a mock?

To stay VERY simple: A mock is a portion of code in your test which is gonna say: when the B class method is called, always return this value: "+++" .

By doing this, you allow yourself having a maintanable and modulable test suite.

In java, I love mockito : http://mockito.org/

Although one of my colleagues is lead maintainer for easymock: http://easymock.org/

Hope this helps. Ask me if you need further help.

EDIT SOME EXAMPLE

With Java and mockito:

public class aUTest {

    protected A a;

    @Mock protected B b;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        a = new A();
        ReflectionTestUtils.setField(a, "b", b);
    }

        @Test
    public void test_A_method_should_not_throw_exception()
            when(b. execute()).thenReturn(true); //just an example of a return value from b. execute()
            Boolean result = a.testHello();

        // Assert
        Assert.assertEquals(true, result);
    }
那小子欠揍 2024-10-13 00:53:09

我为所有模拟对象创建了一个名为 TestHelper 的 Apex 类。我使用常量(静态最终)作为我在其他地方可能需要的值,并使用公共静态字段作为对象。效果很好,并且由于没有使用任何方法,因此不需要测试覆盖率。

public without sharing class TestHelper {
public static final string testPRODUCTNAME = 'test Product Name';
public static final string testCOMPANYID = '2508'; 

public static Account testAccount {
    get{
        Account tAccount = new Account(
            Name = 'Test Account',
            BillingStreet = '123 Main St',
            BillingCity = 'Dallas',
            BillingState = 'TX',
            BillingPostalCode = '75234',
            Website = 'http://www.google.com',
            Phone = '222 345 4567',                
            Subscription_Start_Date__c = system.today(),
            Subscription_End_Date__c = system.today().addDays(30),
            Number_Of_Seats__c = 1,
            companyId__c = testCOMPANYID,
            ZProduct_Name__c = testPRODUCTNAME);      
        insert tAccount;
        return tAccount; 
    }
}

}

I created an Apex class called TestHelper for all my mock objects. I use constants (static final) for values that I might need elsewhere and public static fields for objects. Works great and since no methods are used, no test coverage is needed.

public without sharing class TestHelper {
public static final string testPRODUCTNAME = 'test Product Name';
public static final string testCOMPANYID = '2508'; 

public static Account testAccount {
    get{
        Account tAccount = new Account(
            Name = 'Test Account',
            BillingStreet = '123 Main St',
            BillingCity = 'Dallas',
            BillingState = 'TX',
            BillingPostalCode = '75234',
            Website = 'http://www.google.com',
            Phone = '222 345 4567',                
            Subscription_Start_Date__c = system.today(),
            Subscription_End_Date__c = system.today().addDays(30),
            Number_Of_Seats__c = 1,
            companyId__c = testCOMPANYID,
            ZProduct_Name__c = testPRODUCTNAME);      
        insert tAccount;
        return tAccount; 
    }
}

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文