• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.96
/samples/tutorial/src/main/java/tutorial/domain/MyBusinessService.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package tutorial.domain;
7

8
import static tutorial.persistence.Database.find;
9
import static tutorial.persistence.Database.persist;
10

11
import java.math.BigDecimal;
12
import java.util.List;
13

14
import org.apache.commons.mail.Email;
15
import org.apache.commons.mail.EmailException;
16
import org.apache.commons.mail.SimpleEmail;
17

18
/**
19
 * This class makes use of several idioms which would prevent unit testing with more "conventional" mocking tools. Its
20
 * usage is as simple as it gets: <code>new MyBusinessService(data).doBusinessOperationXyz()</code>. No need to make
21
 * such classes stateless, or worse, <em>singletons</em>; instead, it's designed as a proper object.
22
 * <p>
23
 * One of those "untestable" idioms is the use of a <em>static persistence facade</em> (the
24
 * {@linkplain tutorial.persistence.Database Database} class) for high-level database operations in the context of a
25
 * thread-bound work unit. Since all interaction with the facade is through <code>static</code> methods, client classes
26
 * cannot be unit tested with a tool which only supports <em>mock objects</em>. With JMockit, though, writing such a
27
 * test is just as easy as any other (even easier, in fact, given that <code>static</code> methods don't require an
28
 * instance of the mocked class at all).
29
 * <p>
30
 * Another idiom which runs against limitations of other mocking tools is the direct instantiation and use of external
31
 * dependencies, such as the <a href="http://commons.apache.org/email">Apache Commons Email</a> API, used here to send
32
 * notification e-mails. As demonstrated here, sending an e-mail is simply a matter of instantiating the appropriate
33
 * <code>Email</code> subclass, setting the necessary properties, and calling the <code>send()</code> method. It is
34
 * certainly not a good use case for <em>Dependency Injection</em> (DI).
35
 * <p>
36
 * Finally, consider that application-specific classes like this one are inherently non-reusable in different
37
 * contexts/applications; as such, they can and should be made <code>final</code> to reflect the fact that they are not
38
 * supposed to be extended through inheritance. In the case of reusable <em>base</em> classes, which are specifically
39
 * designed to be extended through inheritance, the judicious use of <code>final</code> for <code>public</code> and
40
 * <code>protected</code> methods is important. (The description of the <em>Template Method</em> pattern in the "GoF"
41
 * book explains why a properly designed template method should be non-overridable.) Unfortunately, the practice of
42
 * <em>designing for extension</em> conflicts with the particular implementation approach employed by other mocking
43
 * tools, which dynamically generate a subclass overriding all non-<code>final</code> methods in the mocked class in
44
 * order to provide mocked behavior. For JMockit, on the other hand, whether a method or class to be mocked is
45
 * <code>final</code> or not is irrelevant, as a radically different mocking approach is employed: class
46
 * <em>redefinition</em> as provided by
47
 * {@link java.lang.instrument.Instrumentation#redefineClasses(java.lang.instrument.ClassDefinition...)}.
48
 */
49
public final class MyBusinessService {
50
    private final EntityX data;
51

52
    public MyBusinessService(EntityX data) {
1✔
53
        this.data = data;
1✔
54
    }
1✔
55

56
    // This method can easily be made transactional, so that any exception thrown during its execution causes a rollback
57
    // somewhere up in the call stack (assuming a transaction gets started in the first place).
58
    public void doBusinessOperationXyz() throws EmailException {
59
        // Locate existing persistent entities of the same entity type (note that the query string is a DSL for querying
60
        // persistent domain entities, written in terms of the domain, not in terms of relational tables and columns):
61
        List<EntityX> items = find("select item from EntityX item where item.someProperty=?1", data.getSomeProperty());
1✔
62

63
        // Compute or obtain from another service a total value for the new persistent entity:
64
        BigDecimal total = new BigDecimal("12.30");
1✔
65
        data.setTotal(total);
1✔
66

67
        // Persist the entity (no DAO required for such a common, high-level, operation):
68
        persist(data);
1✔
69

70
        sendNotificationEmail(items);
1✔
71
    }
1✔
72

73
    private void sendNotificationEmail(List<EntityX> items) throws EmailException {
74
        Email email = new SimpleEmail();
1✔
75
        email.setSubject("Notification about processing of ...");
1✔
76
        email.addTo(data.getCustomerEmail());
1✔
77

78
        // Other e-mail parameters, such as the host name of the mail server, have defaults defined through external
79
        // configuration.
80

81
        String message = buildNotificationMessage(items);
1✔
82
        email.setMsg(message);
1✔
83

84
        email.send();
1✔
85
    }
1✔
86

87
    private static String buildNotificationMessage(List<EntityX> items) {
88
        StringBuilder message = new StringBuilder();
1✔
89

90
        for (EntityX item : items) {
1!
91
            message.append(item.getSomeProperty()).append(" Total: ").append(item.getTotal());
×
92
        }
×
93

94
        return message.toString();
1✔
95
    }
96
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc